aboutsummaryrefslogtreecommitdiffstats
path: root/global-functions
diff options
context:
space:
mode:
Diffstat (limited to 'global-functions')
-rw-r--r--global-functions396
1 files changed, 0 insertions, 396 deletions
diff --git a/global-functions b/global-functions
deleted file mode 100644
index f510218..0000000
--- a/global-functions
+++ /dev/null
@@ -1,396 +0,0 @@
-#!rsc
-# RouterOS script: global-functions
-# Copyright (c) 2013-2020 Christian Hesse <mail@eworm.de>
-# Michael Gisbers <michael@gisbers.de>
-#
-# global functions
-
-# expected configuration version
-:global ExpectedConfigVersion 10;
-
-# global variables not to be changed by user
-:global SentConfigChangesNotification "-";
-:global SentRouterosUpdateNotification "-";
-:global SentLteFirmwareUpgradeNotification "-";
-:global Identity [ / system identity get name ];
-
-# global functions
-:global UrlEncode;
-:global CharacterReplace;
-:global CertificateDownload;
-:global CertificateAvailable;
-:global SendEMail;
-:global SendTelegram;
-:global SendNotification;
-:global GetMacVendor;
-:global CleanFilePath;
-:global DownloadPackage;
-:global ScriptLock;
-:global ScriptFromTerminal;
-:global WaitForFile;
-:global ParseKeyValueStore;
-:global GetRandom;
-:global RandomDelay;
-:global DeviceInfo;
-
-# url encoding
-:set UrlEncode do={
- :local Input [ :tostr $1 ];
- :local Return "";
-
- :if ([ :len $Input ] > 0) do={
- :local Chars " !\"#\$%&'()*+,:;<=>\?@[\\]^`{|}~";
- :local Subs { "%20"; "%21"; "%22"; "%23"; "%24"; "%25"; "%26"; "%27"; "%28"; "%29";
- "%2A"; "%2B"; "%2C"; "%3A"; "%3B"; "%3C"; "%3D"; "%3E"; "%3F"; "%40";
- "%5B"; "%5C"; "%5D"; "%5E"; "%60"; "%7B"; "%7C"; "%7D"; "%7E" };
-
- :for I from=0 to=([ :len $Input ] - 1) do={
- :local Char [ :pick $Input $I ];
- :local Replace [ :find $Chars $Char ];
-
- :if ([ :len $Replace ] > 0) do={
- :set Char ($Subs->$Replace);
- }
- :set Return ($Return . $Char);
- }
- }
-
- :return $Return;
-}
-
-# character replace
-:set CharacterReplace do={
- :local String [ :tostr $1 ];
- :local ReplaceFrom [ :tostr $2 ];
- :local ReplaceWith [ :tostr $3 ];
- :local Len [ :len $ReplaceFrom ];
- :local Return "";
-
- :if ($ReplaceFrom = "") do={
- :return $String;
- }
-
- :while ([ :typeof [ :find $String $ReplaceFrom ] ] != "nil") do={
- :local Pos [ :find $String $ReplaceFrom ];
- :set Return ($Return . [ :pick $String 0 $Pos ] . $ReplaceWith);
- :set String [ :pick $String ($Pos + $Len) 999 ];
- }
-
- :return ($Return . $String);
-}
-
-# download and import certificate
-:set CertificateDownload do={
- :local CommonName [ :tostr $1 ];
-
- :global ScriptUpdatesBaseUrl;
- :global ScriptUpdatesUrlSuffix;
-
- :global CharacterReplace;
- :global UrlEncode;
- :global WaitForFile;
-
- :log info ("Downloading and importing certificate with " . \
- "CommonName \"" . $CommonName . "\".");
- :do {
- :local LocalFileName ($CommonName . ".pem");
- :local UrlFileName ([ $UrlEncode $CommonName ] . ".pem");
- / tool fetch check-certificate=yes-without-crl \
- ($ScriptUpdatesBaseUrl . "certs/" . \
- $UrlFileName . $ScriptUpdatesUrlSuffix) \
- dst-path=$LocalFileName;
- $WaitForFile $LocalFileName;
- / certificate import file-name=$LocalFileName passphrase="";
- / file remove $LocalFileName;
-
- :foreach Cert in=[ / certificate find where name~("^" . $LocalFileName . "_[0-9]+\$") ] do={
- / certificate set $Cert name=[ $CharacterReplace [ $CharacterReplace [ get $Cert common-name ] " " "-" ] "---" "-" ];
- }
- } on-error={
- :log warning "Failed imprting certificate!";
- }
-}
-
-# check and download required certificate
-:set CertificateAvailable do={
- :local CommonName [ :tostr $1 ];
-
- :global CertificateDownload;
-
- :if ([ / certificate print count-only where common-name=$CommonName ] = 0) do={
- :log info ("Certificate with CommonName \"" . $CommonName . "\" not available.");
- $CertificateDownload $CommonName;
- }
-}
-
-# send notification via e-mail
-:set SendEMail do={
- :local Subject [ :tostr $1 ];
- :local Message [ :tostr $2 ];
- :local Attach [ :tostr $3 ];
-
- :global Identity;
- :global EmailGeneralTo;
- :global EmailGeneralCc;
-
- :if ([ :len $EmailGeneralTo ] > 0) do={
- :do {
- :local Signature [ / system note get note ];
- :if ([ :len $Signature ] > 0) do={
- :set Signature ("\n-- \n" . $Signature);
- }
- / tool e-mail send to=$EmailGeneralTo cc=$EmailGeneralCc \
- subject=("[" . $Identity . "] " . $Subject) \
- body=($Message . $Signature) file=$Attach;
- } on-error={
- :log warning "Failed sending notification mail!";
- }
- }
-}
-
-# send notification via telegram
-:set SendTelegram do={
- :local Subject [ :tostr $1 ];
- :local Message [ :tostr $2 ];
- :local Silent [ :tostr $3 ];
-
- :global Identity;
- :global TelegramTokenId;
- :global TelegramChatId;
-
- :global UrlEncode;
- :global CertificateAvailable;
-
- :if ([ :len $TelegramTokenId ] > 0 && [ :len $TelegramChatId ] > 0) do={
- $CertificateAvailable "Go Daddy Secure Certificate Authority - G2";
- :do {
- / tool fetch check-certificate=yes-without-crl keep-result=no http-method=post \
- ("https://api.telegram.org/bot" . $TelegramTokenId . "/sendMessage") \
- http-data=("chat_id=" . $TelegramChatId . "&disable_notification=" . $Silent . \
- "&text=" . [ $UrlEncode ("[" . $Identity . "] " . $Subject . "\n\n" . $Message) ]);
- } on-error={
- :log warning "Failed sending telegram notification!";
- }
- }
-}
-
-# send notification via e-mail and telegram
-# Note that attachment is ignored for telegram, silent is ignored for e-mail!
-:set SendNotification do={
- :local Subject [ :tostr $1 ];
- :local Message [ :tostr $2 ];
- :local Attach [ :tostr $3 ];
- :local Silent [ :tostr $4 ];
-
- :global SendEMail;
- :global SendTelegram;
-
- $SendEMail $Subject $Message $Attach;
- $SendTelegram $Subject $Message $Silent;
-}
-
-
-# get MAC vendor
-:set GetMacVendor do={
- :local Mac [ :tostr $1 ];
-
- :global CertificateAvailable;
-
- :do {
- :local Vendor;
- $CertificateAvailable "Let's Encrypt Authority X3";
- :set Vendor ([ / tool fetch check-certificate=yes-without-crl \
- ("https://api.macvendors.com/" . [ :pick $Mac 0 8 ]) output=user as-value ]->"data");
- :return $Vendor;
- } on-error={
- :return "unknown vendor";
- }
-}
-
-# clean file path
-:set CleanFilePath do={
- :local Path [ :tostr $1 ];
-
- :global CharacterReplace;
-
- :while ($Path ~ "//") do={
- :set $Path [ $CharacterReplace $Path "//" "/" ];
- }
- :if ([ :pick $Path 0 ] = "/") do={
- :set Path [ :pick $Path 1 [ :len $Path ] ];
- }
- :if ([ :pick $Path ([ :len $Path ] - 1) ] = "/") do={
- :set Path [ :pick $Path 0 ([ :len $Path ] - 1) ];
- }
-
- :return $Path;
-}
-
-# download package from upgrade server
-:set DownloadPackage do={
- :local PkgName [ :tostr $1 ];
- :local PkgVer [ :tostr $2 ];
- :local PkgArch [ :tostr $3 ];
- :local PkgDir [ :tostr $4 ];
-
- :global CertificateAvailable;
- :global CleanFilePath;
- :global WaitForFile;
-
- :if ([ :len $PkgName ] = 0) do={ return false; }
- :if ([ :len $PkgVer ] = 0) do={ :set PkgVer [ / system package update get installed-version ]; }
- :if ([ :len $PkgArch ] = 0) do={ :set PkgArch [ / system resource get architecture-name ]; }
-
- :local PkgFile ($PkgName . "-" . $PkgVer . "-" . $PkgArch . ".npk");
- :if ($PkgArch = "x86_64") do={
- :set PkgFile ($PkgName . "-" . $PkgVer . ".npk");
- }
- :local PkgDest [ $CleanFilePath ($PkgDir . "/" . $PkgFile) ];
-
- $CertificateAvailable "Let's Encrypt Authority X3";
-
- :local Retry 3;
- :while ($Retry > 0) do={
- :do {
- / tool fetch check-certificate=yes-without-crl \
- ("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile) \
- dst-path=$PkgDest;
- $WaitForFile $PkgDest;
-
- :if ([ / file get [ find where name=$PkgDest ] type ] = "package") do={
- :return true;
- }
- } on-error={
- # catch error and fall through
- }
-
- / file remove [ find where name=$PkgDest ];
- :set Retry ($Retry - 1);
- }
-
- :return false;
-}
-
-# lock script against multiple invocation
-:set ScriptLock do={
- :local Script [ :tostr $1 ];
-
- :if ([ / system script job print count-only where script=$Script ] > 1) do={
- :log debug ("Script " . $Script . " started more than once... Aborting.");
- :error "Locked."
- }
-}
-
-# check if script is run from terminal
-:set ScriptFromTerminal do={
- :local Script [ :tostr $1 ];
-
- :foreach Job in=[ / system script job find where script=$Script ] do={
- :set Job [ / system script job get $Job ];
- :while ([ :typeof ($Job->"parent") ] = "id") do={
- :set Job [ / system script job get [ find where .id=($Job->"parent") ] ];
- }
- :if (($Job->"type") = "login") do={
- :log debug ("Script " . $Script . " started from terminal.");
- :return true;
- }
- }
-
- :return false;
-}
-
-# wait for file to be available
-:set WaitForFile do={
- :global CleanFilePath;
-
- :local FileName [ $CleanFilePath [ :tostr $1 ] ];
- :local I 0;
-
- :while ([ file print count-only where name=$FileName ] = 0) do={
- :if ($I > 20) do={
- :return false;
- }
- :delay 100ms;
- :set I ($I + 1);
- }
- :return true;
-}
-
-# parse key value store
-:set ParseKeyValueStore do={
- :global CharacterReplace;
-
- :local Source $1;
- :if ([ :typeof $Source ] != "array") do={
- :set Source [ :tostr $1 ];
- }
- :local Result [ :toarray "" ];
- :foreach KeyValue in=[ :toarray $Source ] do={
- :set KeyValue [ :toarray [ $CharacterReplace $KeyValue "=" "," ] ];
- :set ($Result->($KeyValue->0)) ($KeyValue->1);
- }
- :return $Result;
-}
-
-# generate random number
-# Warning: This is a *very* weak algorithm and in *no way*
-# useful for cryptography or similar!
-:set GetRandom do={
- :local Max ([ :tonum $1 ] + 1);
- :local Sum 0;
-
- :foreach Interface in=[ /interface find ] do={
- :set Sum ($Sum + [ /interface get $Interface tx-byte ]);
- }
- :return ($Sum % $Max);
-}
-
-# delay a random amount of seconds
-:set RandomDelay do={
- :global GetRandom;
-
- :delay ([ $GetRandom $1 ] . "s");
-}
-
-# get readable device info
-:set DeviceInfo do={
- :global ExpectedConfigVersion;
- :global GlobalConfigVersion;
- :global Identity;
-
- :local Resource [ / system resource get ];
- :local RouterBoard [ / system routerboard get ];
- :local Update [ / system package update get ];
-
- :local Info ( \
- "Hostname: " . $Identity . "\n" . \
- "Board name: " . $Resource->"board-name" . "\n" . \
- "Architecture: " . $Resource->"architecture-name");
- :if ($RouterBoard->"routerboard" = true) do={
- :local Revision "";
- :if ([ :len ($RouterBoard->"revision") ] > 0) do={
- :set Revision (" " . $RouterBoard->"revision");
- }
- :set Info ($Info . "\n" . \
- "Model: " . $RouterBoard->"model" . $Revision . "\n" . \
- "Serial number: " . $RouterBoard->"serial-number");
- }
- :set Info ($Info . "\n" . \
- "RouterOS:\n" . \
- " Channel: " . $Update->"channel" . "\n" . \
- " Installed: " . $Update->"installed-version");
- :if ([ :typeof ($Update->"latest-version") ] != "nothing" && \
- $Update->"installed-version" != $Update->"latest-version") do={
- :set Info ($Info . "\n" . \
- " Available: " . $Update->"latest-version");
- }
- :set Info ($Info . "\n" . \
- "RouterOS-Scripts Configuration Version:\n" . \
- " Current: " . $GlobalConfigVersion);
- :if ($GlobalConfigVersion != $ExpectedConfigVersion) do={
- :set Info ($Info . "\n" . \
- " Expected: " . $ExpectedConfigVersion);
- }
-
- :return $Info;
-}