diff options
Diffstat (limited to 'global-functions')
-rw-r--r-- | global-functions | 396 |
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; -} |