From 2f946008595f8f6b2df6eec89700d993cffbd563 Mon Sep 17 00:00:00 2001 From: shokinn Date: Sat, 3 Jan 2026 20:12:42 +0100 Subject: [PATCH 1/3] fix typo --- global-functions-custom-phg.rsc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global-functions-custom-phg.rsc b/global-functions-custom-phg.rsc index f4f1c52..df1adc2 100644 --- a/global-functions-custom-phg.rsc +++ b/global-functions-custom-phg.rsc @@ -19,7 +19,7 @@ # Function: safelyResolve # - Takes a DNS string (e.g. "example.com") # - Takes an IP type [ipv4, ipv6] -# - Returns a string of and IP address or false if it can't be resolved +# - Returns a string of an IP address or false if it can't be resolved :set SafeResolve do={ :do { :local DomainName [ :tostr $1 ]; From 9d98352e65e90f9cf9d1bb16a54ffc10eb38c567 Mon Sep 17 00:00:00 2001 From: shokinn Date: Sun, 4 Jan 2026 02:01:52 +0100 Subject: [PATCH 2/3] Update template --- doc/template.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ template.rsc.tpl | 34 +++++++++++++++++----------------- 2 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 doc/template.md diff --git a/doc/template.md b/doc/template.md new file mode 100644 index 0000000..1e4f9d8 --- /dev/null +++ b/doc/template.md @@ -0,0 +1,48 @@ +# Script name + +[⬅️ Go back to main README](../README.md) + +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. + +## Table of Contents + +- [Script name](#script-name) + - [Table of Contents](#table-of-contents) + - [Description](#description) + - [Requirements and installation](#requirements-and-installation) + - [Configuration](#configuration) + - [Usage and invocation](#usage-and-invocation) + - [See also](#see-also) + +## Description + +Function description of the script and which goal it should achieve. + +## Requirements and installation + +Just install the script: + +```rsc +$ScriptInstallUpdate script-file-name-without-filename-extension "base-url=https://git.s1q.dev/phg/routeros-scripts-custom/raw/branch/main/"; +``` + +## Configuration + +What to configure to run the script + +## Usage and invocation + +How to run the script: + +```rsc +/system/script/run script-file-name-without-filename-extension; +``` + +## See also + +* ... + +--- +[⬅️ Go back to main README](../README.md) +[⬆️ Go back to top](#top) diff --git a/template.rsc.tpl b/template.rsc.tpl index b596501..76e110c 100644 --- a/template.rsc.tpl +++ b/template.rsc.tpl @@ -8,26 +8,26 @@ # # https://git.s1q.dev/phg/routeros-scripts-custom/about/doc/.md -:global GlobalFunctionsReady; -:while ($GlobalFunctionsReady != true) do={ :delay 500ms; } - :local ExitOK false; -:do { +onerror Err { + :global GlobalConfigReady; :global GlobalFunctionsReady; + :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ + do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; :local ScriptName [ :jobname ]; :global LogPrint; - :global ParseKeyValueStore; - :global ScriptLock; + :global ScriptFromTerminal; + :global SendNotification2; - # Local/global script specific variables - - :if ([ $ScriptLock $ScriptName ] = false) do={ - :set ExitOK true; - :error false; + # Log notifications locally, or send them via email/pushover etc. when not run from terminal + # Usually used for important notifications only + :if ([ $ScriptFromTerminal $ScriptName ] = true) do={ + # Add Script from here for running from terminal: + $LogPrint info $ScriptName ("Hello world!"); + } else={ + # Add Script from here for running as scheduled script: + $SendNotification2 ({ origin=$ScriptName; subject="Hello..."; message="... world!" }); } - - # Add Script from here: - -} on-error={ - :global ExitError; $ExitError $ExitOK [ :jobname ]; -} \ No newline at end of file +} do={ + :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; +} From 7a8adad529f684ebd466e1af95924875b2eb0959 Mon Sep 17 00:00:00 2001 From: shokinn Date: Sun, 4 Jan 2026 02:02:32 +0100 Subject: [PATCH 3/3] Add my DNS to IPv6 Subnet resolver to my custom scripts repo --- dns-to-ipv6-subnet-resolver.rsc | 78 +++++++++++++++++++++++++ doc/dns-to-ipv6-subnet-resolver.md | 94 ++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 dns-to-ipv6-subnet-resolver.rsc create mode 100644 doc/dns-to-ipv6-subnet-resolver.md diff --git a/dns-to-ipv6-subnet-resolver.rsc b/dns-to-ipv6-subnet-resolver.rsc new file mode 100644 index 0000000..d082ff8 --- /dev/null +++ b/dns-to-ipv6-subnet-resolver.rsc @@ -0,0 +1,78 @@ +# ------------------------------------------------------------------------------- +# Script to grab IPv6 Addresses from DNS an converting them to subnets +# +# by Philip 'ShokiNN' Henning +# RouterOS compatibility: 7+ +# Version 1.1 +# last update: 03.01.2026 +# https://git.s1q.dev/phg/routeros-scripts-custom/about/doc/dns-to-ipv6-subnet-resolver.md +# ------------------------------------------------------------------------------- + +:local ExitOK false; +onerror Err { + :global GlobalConfigReady; :global GlobalFunctionsReady; :global GlobalFunctionsCustomPhgReady; + :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true || $GlobalFunctionsCustomPhgReady != true) \ + do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; + :local ScriptName [ :jobname ]; + + :global LogPrint; + :global ParseKeyValueStore; + :global ScriptLock; + :global SafeResolve; + :global PhgDomainToIpv6Subnet; + :global PhgIpv6AddressList; + :global PhgIpv6AddressListCommentPrefix; + + :if ([ $ScriptLock $ScriptName ] = false) do={ + :set ExitOK true; + :error false; + } + + :if ([:typeof $PhgDomainToIpv6Subnet ] != "array" || ([:len $PhgDomainToIpv6Subnet ] = 0)) do={ + $LogPrint error $ScriptName ("Variable 'PhgDomainToIpv6Subnet' is not set or not of type 'array'. Please set it to an array of domain/subnet-length/comment tuples."); + :error true; + } + + :if ([:typeof $PhgIpv6AddressList ] != "str" || $PhgIpv6AddressList = "") do={ + $LogPrint error $ScriptName ("Variable 'PhgIpv6AddressList' is not set or not of type 'string'. Please set it to the name of the IPv6 address list to use."); + :error true; + } + + # Log "run of script" + $LogPrint info $ScriptName ("running"); + + :local index 0; + :foreach i in=$PhgDomainToIpv6Subnet do={ + onerror SubnetErr { + :local configDomain ("$($i->0)"); + :local configSubnetLength ("$($i->1)"); + :local configComment ""; + if ([:typeof $PhgIpv6AddressListCommentPrefix ] != "str" || $PhgIpv6AddressListCommentPrefix = "") do={ + :set configComment ("$($i->2)"); + } else={ + :set configComment ("$PhgIpv6AddressListCommentPrefix" . " " . "$($i->2)"); + } + :local dnsIp ""; + + $LogPrint info $ScriptName ("Start configuring domain: $configDomain"); + /ipv6/firewall/address-list/remove [/ipv6/firewall/address-list/find list="$PhgIpv6AddressList" comment="$configComment"]; + + :set dnsIp [$SafeResolve $configDomain ipv6]; + :if ($dnsIp != false) do={ + /ipv6/firewall/address-list/add list="$PhgIpv6AddressList" address="$dnsIp/$configSubnetLength" comment="$configComment"; + :local addedSubnet [:pick [/ipv6/firewall/address-list/get [/ipv6/firewall/address-list/find list="$PhgIpv6AddressList" comment="$configComment"]] 1]; + $LogPrint info $ScriptName ("domain: $configDomain - Set to: $addedSubnet"); + } + + $LogPrint info $ScriptName ("Finished configuring domain: $configDomain"); + } do={ + #TODO Send error via Notification system + $LogPrint error $ScriptName ("Error processing entry index $index: $i - $SubnetErr"); + } + }; + :set index; + + $LogPrint info $ScriptName ("finished"); +} do={ + :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; +} diff --git a/doc/dns-to-ipv6-subnet-resolver.md b/doc/dns-to-ipv6-subnet-resolver.md new file mode 100644 index 0000000..b13a4a0 --- /dev/null +++ b/doc/dns-to-ipv6-subnet-resolver.md @@ -0,0 +1,94 @@ +# DNS to IPv6 subnet resolver + +[⬅️ Go back to main README](../README.md) + +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. + +## Table of Contents + +- [DNS to IPv6 subnet resolver](#dns-to-ipv6-subnet-resolver) + - [Table of Contents](#table-of-contents) + - [Description](#description) + - [Requirements and installation](#requirements-and-installation) + - [Configuration](#configuration) + - [`PhgIpv6AddressList`](#phgipv6addresslist) + - [`PhgDomainToIpv6Subnet`](#phgdomaintoipv6subnet) + - [`PhgIpv6AddressListCommentPrefix`](#phgipv6addresslistcommentprefix) + - [Usage and invocation](#usage-and-invocation) + +## Description + +This script resolved IPv6 addresses from a domain and calculates the Subnet from the configured subnet length. + +## Requirements and installation + +Just install the script: + +```rsc +$ScriptInstallUpdate dns-to-ipv6-subnet-resolver "base-url=https://git.s1q.dev/phg/routeros-scripts-custom/raw/branch/main/"; +/system/script/set [find name="dns-to-ipv6-subnet-resolver"] policy=read,write,test +``` + +## Configuration + +Edit `global-config-overlay` and Add the following variables. + +| Variable name | Required | Data type | Example | Description | +| :-------------------------------- | :------- | :-------- | :---------------------------------- | :--------------------------------------------------------------------------- | +| `PhgIpv6AddressList` | true | String | `resolved_ipv6_subnets` | IPv6 address list (address list which will contain the resolved subnets) | +| `PhgDomainToIpv6Subnet` | true | tuple | `{"example.com";64;"example.com"};` | Object containing a domain, a prefix length and a comment for the List entry | +| `PhgIpv6AddressListCommentPrefix` | false | String | `Resolved subnet for` | If set, prefixes the comment for the address list | + +### `PhgIpv6AddressList` + +Example: + +```rsc +:global PhgIpv6AddressList "resolved_ipv6_subnets"; +``` + +### `PhgDomainToIpv6Subnet` + +Example: + +```rsc +:global PhgDomainToIpv6Subnet { + {"example.com";64;"example.com"}; + {"example.net";56;"example.net - Home IP of John Doe"}; +}; +``` + +`PhgDomainToIpv6Subnet` tuple variables: + +| Object variable | Data type | Example | Description | +| :-------------- | :-------- | :-------------- | :------------------------------------------------------------------------------------ | +| Domain | String | `"example.com"` | The domain which the IPv6 address should be resolved | +| Prefix length | Integer | `64` | The prefix length for the resolved IPv6 address. Used to calculate the subnet address | +| Comment | String | `"example.com"` | Comment for the list entry | + +### `PhgIpv6AddressListCommentPrefix` + +Example: + +```rsc +:global PhgIpv6AddressListCommentPrefix "Resolved subnet for"; +``` + +## Usage and invocation + +How to run the script manually: + +```rsc +/system/script/run dns-to-ipv6-subnet-resolver; +``` + +Setup a Scheduler to run the script regularly: + +```rsc +/system/scheduler/add name="dns-to-ipv6-subnet-resolver" interval="00:05:00" policy="read,write,test" on-event="/system/script/run dns-to-ipv6-subnet-resolver;"; +``` + +--- +[⬅️ Go back to main README](../README.md) +[⬆️ Go back to top](#top)