summaryrefslogtreecommitdiff
path: root/src/validators
diff options
context:
space:
mode:
authorkumvijaya <kumvijaya@gmail.com>2024-05-21 16:41:14 +0530
committerkumvijaya <kumvijaya@gmail.com>2024-05-21 16:41:14 +0530
commitcc86483fdf7a6bd988f485c06402fd07368dd26e (patch)
tree9d892a9715106cc67bf1e57b15b999aa7e564057 /src/validators
parent704ca2322d0bebcb923f5136f0f69fb23651a484 (diff)
downloadvyos-workflow-test-temp-cc86483fdf7a6bd988f485c06402fd07368dd26e.tar.gz
vyos-workflow-test-temp-cc86483fdf7a6bd988f485c06402fd07368dd26e.zip
T6357: create test repository to validate setup
Diffstat (limited to 'src/validators')
-rw-r--r--src/validators/as-number-list29
-rw-r--r--src/validators/base6427
-rw-r--r--src/validators/bgp-extended-community54
-rw-r--r--src/validators/bgp-large-community53
-rw-r--r--src/validators/bgp-large-community-list34
-rw-r--r--src/validators/bgp-rd-rt59
-rw-r--r--src/validators/bgp-regular-community50
-rw-r--r--src/validators/ddclient-protocol24
-rw-r--r--src/validators/fqdn2
-rw-r--r--src/validators/interface-address3
-rw-r--r--src/validators/ip-address10
-rw-r--r--src/validators/ip-cidr10
-rw-r--r--src/validators/ip-host10
-rw-r--r--src/validators/ip-prefix10
-rw-r--r--src/validators/ip-protocol42
-rw-r--r--src/validators/ipv410
-rw-r--r--src/validators/ipv4-address10
-rw-r--r--src/validators/ipv4-address-exclude7
-rw-r--r--src/validators/ipv4-host10
-rw-r--r--src/validators/ipv4-multicast10
-rw-r--r--src/validators/ipv4-prefix10
-rw-r--r--src/validators/ipv4-prefix-exclude7
-rw-r--r--src/validators/ipv4-range40
-rw-r--r--src/validators/ipv4-range-exclude7
-rw-r--r--src/validators/ipv4-range-mask27
-rw-r--r--src/validators/ipv610
-rw-r--r--src/validators/ipv6-address10
-rw-r--r--src/validators/ipv6-address-exclude7
-rw-r--r--src/validators/ipv6-eui64-prefix16
-rw-r--r--src/validators/ipv6-exclude7
-rw-r--r--src/validators/ipv6-host10
-rw-r--r--src/validators/ipv6-link-local12
-rw-r--r--src/validators/ipv6-multicast10
-rw-r--r--src/validators/ipv6-prefix10
-rw-r--r--src/validators/ipv6-prefix-exclude7
-rw-r--r--src/validators/ipv6-range20
-rw-r--r--src/validators/ipv6-range-exclude7
-rw-r--r--src/validators/ipv6-srv6-segments13
-rw-r--r--src/validators/mac-address2
-rw-r--r--src/validators/mac-address-exclude2
-rw-r--r--src/validators/numeric-exclude8
-rw-r--r--src/validators/port-multi52
-rw-r--r--src/validators/port-range40
-rw-r--r--src/validators/script42
-rw-r--r--src/validators/sysctl24
-rw-r--r--src/validators/timezone33
-rw-r--r--src/validators/vrf-name41
-rw-r--r--src/validators/wireless-phy25
48 files changed, 963 insertions, 0 deletions
diff --git a/src/validators/as-number-list b/src/validators/as-number-list
new file mode 100644
index 0000000..432d441
--- /dev/null
+++ b/src/validators/as-number-list
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) 2022 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if [ $# -lt 1 ]; then
+ echo "Illegal number of parameters"
+ exit 1
+fi
+
+for var in "$@"; do
+ ${vyos_validators_dir}/numeric --range 1-4294967294 $var
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+done
+
+exit 0
diff --git a/src/validators/base64 b/src/validators/base64
new file mode 100644
index 0000000..e2b1e73
--- /dev/null
+++ b/src/validators/base64
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import base64
+from sys import argv
+
+if __name__ == '__main__':
+ if len(argv) != 2:
+ exit(1)
+ try:
+ base64.b64decode(argv[1])
+ except:
+ exit(1)
+ exit(0)
diff --git a/src/validators/bgp-extended-community b/src/validators/bgp-extended-community
new file mode 100644
index 0000000..d666655
--- /dev/null
+++ b/src/validators/bgp-extended-community
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+
+# Copyright 2019-2023 VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+from argparse import ArgumentParser
+from sys import exit
+
+from vyos.template import is_ipv4
+
+COMM_MAX_2_OCTET: int = 65535
+COMM_MAX_4_OCTET: int = 4294967295
+
+if __name__ == '__main__':
+ # add an argument with community
+ parser: ArgumentParser = ArgumentParser()
+ parser.add_argument('community', type=str)
+ args = parser.parse_args()
+
+ for community in args.community.split():
+ if community.count(':') != 1:
+ print("Invalid community format")
+ exit(1)
+ try:
+ # try to extract community parts from an argument
+ comm_left: str = community.split(':')[0]
+ comm_right: int = int(community.split(':')[1])
+
+ # check if left part is an IPv4 address
+ if is_ipv4(comm_left) and 0 <= comm_right <= COMM_MAX_2_OCTET:
+ continue
+ # check if a left part is a number
+ if 0 <= int(comm_left) <= COMM_MAX_2_OCTET \
+ and 0 <= comm_right <= COMM_MAX_4_OCTET:
+ continue
+
+ raise Exception()
+
+ except Exception:
+ # fail if something was wrong
+ print("Invalid community format")
+ exit(1) \ No newline at end of file
diff --git a/src/validators/bgp-large-community b/src/validators/bgp-large-community
new file mode 100644
index 0000000..3863983
--- /dev/null
+++ b/src/validators/bgp-large-community
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+# Copyright 2019-2022 VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+from argparse import ArgumentParser
+from sys import exit
+
+from vyos.template import is_ipv4
+
+COMM_MAX_4_OCTET: int = 4294967295
+
+if __name__ == '__main__':
+ # add an argument with community
+ parser: ArgumentParser = ArgumentParser()
+ parser.add_argument('community', type=str)
+ args = parser.parse_args()
+ community: str = args.community
+ if community.count(':') != 2:
+ print("Invalid community format")
+ exit(1)
+ try:
+ # try to extract community parts from an argument
+ comm_part1: int = int(community.split(':')[0])
+ comm_part2: int = int(community.split(':')[1])
+ comm_part3: int = int(community.split(':')[2])
+
+ # check compatibilities of left and right parts
+ if 0 <= comm_part1 <= COMM_MAX_4_OCTET \
+ and 0 <= comm_part2 <= COMM_MAX_4_OCTET \
+ and 0 <= comm_part3 <= COMM_MAX_4_OCTET:
+ exit(0)
+
+ except Exception:
+ # fail if something was wrong
+ print("Invalid community format")
+ exit(1)
+
+ # fail if none of validators catched the value
+ print("Invalid community format")
+ exit(1) \ No newline at end of file
diff --git a/src/validators/bgp-large-community-list b/src/validators/bgp-large-community-list
new file mode 100644
index 0000000..9ba5b27
--- /dev/null
+++ b/src/validators/bgp-large-community-list
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021-2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+
+pattern = '(.*):(.*):(.*)'
+allowedChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '+', '*', '?', '^', '$', '(', ')', '[', ']', '{', '}', '|', '\\', ':', '-' }
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ sys.exit(1)
+
+ value = sys.argv[1].split(':')
+ if not len(value) == 3:
+ sys.exit(1)
+
+ if not (re.match(pattern, sys.argv[1]) and set(sys.argv[1]).issubset(allowedChars)):
+ sys.exit(1)
+
+ sys.exit(0)
diff --git a/src/validators/bgp-rd-rt b/src/validators/bgp-rd-rt
new file mode 100644
index 0000000..b2b69c9
--- /dev/null
+++ b/src/validators/bgp-rd-rt
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from argparse import ArgumentParser
+from vyos.template import is_ipv4
+
+parser = ArgumentParser()
+group = parser.add_mutually_exclusive_group()
+group.add_argument('--route-distinguisher', action='store', help='Validate BGP route distinguisher')
+group.add_argument('--route-target', action='store', help='Validate one BGP route-target')
+group.add_argument('--route-target-multi', action='store', help='Validate multiple, whitespace separated BGP route-targets')
+args = parser.parse_args()
+
+def is_valid(rt):
+ """ Verify BGP RD/RT - both can be verified using the same logic """
+ # every RD/RT (route distinguisher/route target) needs to have a colon and
+ # must consists of two parts
+ value = rt.split(':')
+ if len(value) != 2:
+ return False
+
+ # An RD/RT must either be only numbers, or the first part must be an IPv4
+ # address
+ if (is_ipv4(value[0]) or value[0].isdigit()) and value[1].isdigit():
+ return True
+ return False
+
+if __name__ == '__main__':
+ if args.route_distinguisher:
+ if not is_valid(args.route_distinguisher):
+ exit(1)
+
+ elif args.route_target:
+ if not is_valid(args.route_target):
+ exit(1)
+
+ elif args.route_target_multi:
+ for rt in args.route_target_multi.split(' '):
+ if not is_valid(rt):
+ exit(1)
+
+ else:
+ parser.print_help()
+ exit(1)
+
+ exit(0)
diff --git a/src/validators/bgp-regular-community b/src/validators/bgp-regular-community
new file mode 100644
index 0000000..d43a71e
--- /dev/null
+++ b/src/validators/bgp-regular-community
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+
+# Copyright 2019-2022 VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+from argparse import ArgumentParser
+from sys import exit
+
+from vyos.template import is_ipv4
+
+COMM_MAX_2_OCTET: int = 65535
+
+if __name__ == '__main__':
+ # add an argument with community
+ parser: ArgumentParser = ArgumentParser()
+ parser.add_argument('community', type=str)
+ args = parser.parse_args()
+ community: str = args.community
+ if community.count(':') != 1:
+ print("Invalid community format")
+ exit(1)
+ try:
+ # try to extract community parts from an argument
+ comm_left: int = int(community.split(':')[0])
+ comm_right: int = int(community.split(':')[1])
+
+ # check compatibilities of left and right parts
+ if 0 <= comm_left <= COMM_MAX_2_OCTET \
+ and 0 <= comm_right <= COMM_MAX_2_OCTET:
+ exit(0)
+ except Exception:
+ # fail if something was wrong
+ print("Invalid community format")
+ exit(1)
+
+ # fail if none of validators catched the value
+ print("Invalid community format")
+ exit(1) \ No newline at end of file
diff --git a/src/validators/ddclient-protocol b/src/validators/ddclient-protocol
new file mode 100644
index 0000000..ce5efbd
--- /dev/null
+++ b/src/validators/ddclient-protocol
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ddclient -list-protocols | grep -vE 'cloudns|porkbun' | grep -qw $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid protocol, please choose from the supported list of protocols"
+ exit 1
+fi
+
+exit 0
diff --git a/src/validators/fqdn b/src/validators/fqdn
new file mode 100644
index 0000000..a65d2d5
--- /dev/null
+++ b/src/validators/fqdn
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+${vyos_libexec_dir}/validate-value --regex "[A-Za-z0-9][-.A-Za-z0-9]*" --value "$1"
diff --git a/src/validators/interface-address b/src/validators/interface-address
new file mode 100644
index 0000000..4c20395
--- /dev/null
+++ b/src/validators/interface-address
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv4-host $1 || ipaddrcheck --is-ipv6-host $1
diff --git a/src/validators/ip-address b/src/validators/ip-address
new file mode 100644
index 0000000..11d6df0
--- /dev/null
+++ b/src/validators/ip-address
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-any-single $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IP address"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ip-cidr b/src/validators/ip-cidr
new file mode 100644
index 0000000..60d2ac2
--- /dev/null
+++ b/src/validators/ip-cidr
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-any-cidr $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IP CIDR"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ip-host b/src/validators/ip-host
new file mode 100644
index 0000000..77c578f
--- /dev/null
+++ b/src/validators/ip-host
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-any-host $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IP host"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ip-prefix b/src/validators/ip-prefix
new file mode 100644
index 0000000..e5a64fe
--- /dev/null
+++ b/src/validators/ip-prefix
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-any-net $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IP prefix"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ip-protocol b/src/validators/ip-protocol
new file mode 100644
index 0000000..c4c8825
--- /dev/null
+++ b/src/validators/ip-protocol
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+from sys import argv,exit
+
+if __name__ == '__main__':
+ if len(argv) != 2:
+ exit(1)
+
+ input = argv[1]
+ try:
+ # IP protocol can be in the range 0 - 255, thus the range must end with 256
+ if int(input) in range(0, 256):
+ exit(0)
+ except ValueError:
+ pass
+
+ pattern = "!?\\b(all|ip|hopopt|icmp|igmp|ggp|ipencap|st|tcp|egp|igp|pup|udp|" \
+ "tcp_udp|hmp|xns-idp|rdp|iso-tp4|dccp|xtp|ddp|idpr-cmtp|ipv6|" \
+ "ipv6-route|ipv6-frag|idrp|rsvp|gre|esp|ah|skip|ipv6-icmp|icmpv6|" \
+ "ipv6-nonxt|ipv6-opts|rspf|vmtp|eigrp|ospf|ax.25|ipip|etherip|" \
+ "encap|99|pim|ipcomp|vrrp|l2tp|isis|sctp|fc|mobility-header|" \
+ "udplite|mpls-in-ip|manet|hip|shim6|wesp|rohc)\\b"
+ if re.match(pattern, input):
+ exit(0)
+
+ print(f'Error: {input} is not a valid IP protocol')
+ exit(1)
diff --git a/src/validators/ipv4 b/src/validators/ipv4
new file mode 100644
index 0000000..8676d58
--- /dev/null
+++ b/src/validators/ipv4
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv4 $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not IPv4"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv4-address b/src/validators/ipv4-address
new file mode 100644
index 0000000..058db08
--- /dev/null
+++ b/src/validators/ipv4-address
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv4-single $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv4 address"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv4-address-exclude b/src/validators/ipv4-address-exclude
new file mode 100644
index 0000000..80ad17d
--- /dev/null
+++ b/src/validators/ipv4-address-exclude
@@ -0,0 +1,7 @@
+#!/bin/sh
+arg="$1"
+if [ "${arg:0:1}" != "!" ]; then
+ exit 1
+fi
+path=$(dirname "$0")
+${path}/ipv4-address "${arg:1}"
diff --git a/src/validators/ipv4-host b/src/validators/ipv4-host
new file mode 100644
index 0000000..74b8c36
--- /dev/null
+++ b/src/validators/ipv4-host
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv4-host $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv4 host"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv4-multicast b/src/validators/ipv4-multicast
new file mode 100644
index 0000000..3f28c51
--- /dev/null
+++ b/src/validators/ipv4-multicast
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv4-multicast $1 && ipaddrcheck --is-ipv4-single $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv4 multicast address"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv4-prefix b/src/validators/ipv4-prefix
new file mode 100644
index 0000000..7e1e0e8
--- /dev/null
+++ b/src/validators/ipv4-prefix
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv4-net $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv4 prefix"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv4-prefix-exclude b/src/validators/ipv4-prefix-exclude
new file mode 100644
index 0000000..4f7de40
--- /dev/null
+++ b/src/validators/ipv4-prefix-exclude
@@ -0,0 +1,7 @@
+#!/bin/sh
+arg="$1"
+if [ "${arg:0:1}" != "!" ]; then
+ exit 1
+fi
+path=$(dirname "$0")
+${path}/ipv4-prefix "${arg:1}"
diff --git a/src/validators/ipv4-range b/src/validators/ipv4-range
new file mode 100644
index 0000000..6492bfc
--- /dev/null
+++ b/src/validators/ipv4-range
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# snippet from https://stackoverflow.com/questions/10768160/ip-address-converter
+ip2dec () {
+ local a b c d ip=$@
+ IFS=. read -r a b c d <<< "$ip"
+ printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))"
+}
+
+error_exit() {
+ echo "Error: $1 is not a valid IPv4 address range"
+ exit 1
+}
+
+# Only run this if there is a hypen present in $1
+if [[ "$1" =~ "-" ]]; then
+ # This only works with real bash (<<<) - split IP addresses into array with
+ # hyphen as delimiter
+ readarray -d - -t strarr <<< $1
+
+ ipaddrcheck --is-ipv4-single ${strarr[0]}
+ if [ $? -gt 0 ]; then
+ error_exit $1
+ fi
+
+ ipaddrcheck --is-ipv4-single ${strarr[1]}
+ if [ $? -gt 0 ]; then
+ error_exit $1
+ fi
+
+ start=$(ip2dec ${strarr[0]})
+ stop=$(ip2dec ${strarr[1]})
+ if [ $start -ge $stop ]; then
+ error_exit $1
+ fi
+
+ exit 0
+fi
+
+error_exit $1
diff --git a/src/validators/ipv4-range-exclude b/src/validators/ipv4-range-exclude
new file mode 100644
index 0000000..3787b4d
--- /dev/null
+++ b/src/validators/ipv4-range-exclude
@@ -0,0 +1,7 @@
+#!/bin/sh
+arg="$1"
+if [ "${arg:0:1}" != "!" ]; then
+ exit 1
+fi
+path=$(dirname "$0")
+${path}/ipv4-range "${arg:1}"
diff --git a/src/validators/ipv4-range-mask b/src/validators/ipv4-range-mask
new file mode 100644
index 0000000..9373328
--- /dev/null
+++ b/src/validators/ipv4-range-mask
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+error_exit() {
+ echo "Error: $1 is not a valid IPv4 address range or these IPs are not under /$2"
+ exit 1
+}
+
+# Check if address range is under the same netmask
+# -m - mask
+# -r - IP range in format x.x.x.x-y.y.y.y
+while getopts m:r: flag
+do
+ case "${flag}" in
+ m) mask=${OPTARG};;
+ r) range=${OPTARG}
+ esac
+done
+
+if [[ "${range}" =~ "-" ]]&&[[ ! -z ${mask} ]]; then
+ ipaddrcheck --range-prefix-length ${mask} --is-ipv4-range ${range}
+ if [ $? -gt 0 ]; then
+ error_exit ${range} ${mask}
+ fi
+ exit 0
+fi
+
+error_exit ${range} ${mask}
diff --git a/src/validators/ipv6 b/src/validators/ipv6
new file mode 100644
index 0000000..4ae130e
--- /dev/null
+++ b/src/validators/ipv6
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv6 $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not IPv6"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv6-address b/src/validators/ipv6-address
new file mode 100644
index 0000000..1fca776
--- /dev/null
+++ b/src/validators/ipv6-address
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv6-single $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv6 address"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv6-address-exclude b/src/validators/ipv6-address-exclude
new file mode 100644
index 0000000..be1d3db
--- /dev/null
+++ b/src/validators/ipv6-address-exclude
@@ -0,0 +1,7 @@
+#!/bin/sh
+arg="$1"
+if [ "${arg:0:1}" != "!" ]; then
+ exit 1
+fi
+path=$(dirname "$0")
+${path}/ipv6-address "${arg:1}"
diff --git a/src/validators/ipv6-eui64-prefix b/src/validators/ipv6-eui64-prefix
new file mode 100644
index 0000000..d7f2626
--- /dev/null
+++ b/src/validators/ipv6-eui64-prefix
@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+
+# Validator used to check if given IPv6 prefix is of size /64 required by EUI64
+
+from sys import argv
+from sys import exit
+
+if __name__ == '__main__':
+ if len(argv) != 2:
+ exit(1)
+
+ prefix = argv[1]
+ if prefix.split('/')[1] == '64':
+ exit(0)
+
+ exit(1)
diff --git a/src/validators/ipv6-exclude b/src/validators/ipv6-exclude
new file mode 100644
index 0000000..893eeab
--- /dev/null
+++ b/src/validators/ipv6-exclude
@@ -0,0 +1,7 @@
+#!/bin/sh
+arg="$1"
+if [ "${arg:0:1}" != "!" ]; then
+ exit 1
+fi
+path=$(dirname "$0")
+${path}/ipv6 "${arg:1}"
diff --git a/src/validators/ipv6-host b/src/validators/ipv6-host
new file mode 100644
index 0000000..7085809
--- /dev/null
+++ b/src/validators/ipv6-host
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv6-host $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv6 host"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv6-link-local b/src/validators/ipv6-link-local
new file mode 100644
index 0000000..6ac3ea7
--- /dev/null
+++ b/src/validators/ipv6-link-local
@@ -0,0 +1,12 @@
+#!/usr/bin/python3
+
+import sys
+from vyos.utils.network import is_ipv6_link_local
+
+if __name__ == '__main__':
+ if len(sys.argv)>1:
+ addr = sys.argv[1]
+ if not is_ipv6_link_local(addr):
+ sys.exit(1)
+
+ sys.exit(0)
diff --git a/src/validators/ipv6-multicast b/src/validators/ipv6-multicast
new file mode 100644
index 0000000..5aa7d73
--- /dev/null
+++ b/src/validators/ipv6-multicast
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv6-multicast $1 && ipaddrcheck --is-ipv6-single $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv6 multicast address"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv6-prefix b/src/validators/ipv6-prefix
new file mode 100644
index 0000000..890dda7
--- /dev/null
+++ b/src/validators/ipv6-prefix
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ipaddrcheck --is-ipv6-net $1
+
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv6 prefix"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/src/validators/ipv6-prefix-exclude b/src/validators/ipv6-prefix-exclude
new file mode 100644
index 0000000..6fa4f1d
--- /dev/null
+++ b/src/validators/ipv6-prefix-exclude
@@ -0,0 +1,7 @@
+#!/bin/sh
+arg="$1"
+if [ "${arg:0:1}" != "!" ]; then
+ exit 1
+fi
+path=$(dirname "$0")
+${path}/ipv6-prefix "${arg:1}"
diff --git a/src/validators/ipv6-range b/src/validators/ipv6-range
new file mode 100644
index 0000000..7080860
--- /dev/null
+++ b/src/validators/ipv6-range
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+
+from ipaddress import IPv6Address
+from sys import argv, exit
+
+if __name__ == '__main__':
+ if len(argv) > 1:
+ # try to pass validation and raise an error if failed
+ try:
+ ipv6_range = argv[1]
+ range_left = ipv6_range.split('-')[0]
+ range_right = ipv6_range.split('-')[1]
+ if not IPv6Address(range_left) < IPv6Address(range_right):
+ raise ValueError(f'left element {range_left} must be less than right element {range_right}')
+ except Exception as err:
+ print(f'Error: {ipv6_range} is not a valid IPv6 range: {err}')
+ exit(1)
+ else:
+ print('Error: an IPv6 range argument must be provided')
+ exit(1)
diff --git a/src/validators/ipv6-range-exclude b/src/validators/ipv6-range-exclude
new file mode 100644
index 0000000..912b55a
--- /dev/null
+++ b/src/validators/ipv6-range-exclude
@@ -0,0 +1,7 @@
+#!/bin/sh
+arg="$1"
+if [ "${arg:0:1}" != "!" ]; then
+ exit 1
+fi
+path=$(dirname "$0")
+${path}/ipv6-range "${arg:1}"
diff --git a/src/validators/ipv6-srv6-segments b/src/validators/ipv6-srv6-segments
new file mode 100644
index 0000000..e72a4f9
--- /dev/null
+++ b/src/validators/ipv6-srv6-segments
@@ -0,0 +1,13 @@
+#!/bin/sh
+segments="$1"
+export IFS="/"
+
+for ipv6addr in $segments; do
+ ipaddrcheck --is-ipv6-single $ipv6addr
+ if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv6 address"
+ exit 1
+ fi
+done
+exit 0
+
diff --git a/src/validators/mac-address b/src/validators/mac-address
new file mode 100644
index 0000000..bb859a6
--- /dev/null
+++ b/src/validators/mac-address
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+${vyos_libexec_dir}/validate-value --regex "([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})" --value "$1"
diff --git a/src/validators/mac-address-exclude b/src/validators/mac-address-exclude
new file mode 100644
index 0000000..c449130
--- /dev/null
+++ b/src/validators/mac-address-exclude
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+${vyos_libexec_dir}/validate-value --regex "!([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})" --value "$1"
diff --git a/src/validators/numeric-exclude b/src/validators/numeric-exclude
new file mode 100644
index 0000000..676a240
--- /dev/null
+++ b/src/validators/numeric-exclude
@@ -0,0 +1,8 @@
+#!/bin/sh
+path=$(dirname "$0")
+num="${@: -1}"
+if [ "${num:0:1}" != "!" ]; then
+ ${path}/numeric $@
+else
+ ${path}/numeric ${@:1:$#-1} ${num:1}
+fi
diff --git a/src/validators/port-multi b/src/validators/port-multi
new file mode 100644
index 0000000..ed6ff68
--- /dev/null
+++ b/src/validators/port-multi
@@ -0,0 +1,52 @@
+#!/usr/bin/python3
+
+from sys import argv
+from sys import exit
+import re
+
+from vyos.utils.file import read_file
+
+services_file = '/etc/services'
+
+def get_services():
+ names = []
+ service_data = read_file(services_file, "")
+ for line in service_data.split("\n"):
+ if not line or line[0] == '#':
+ continue
+ tmp = line.split()
+ names.append(tmp[0])
+ if len(tmp) > 2:
+ # Add port aliases to service list, too
+ names.extend(tmp[2:])
+ # remove duplicate entries (e.g. echo) from list
+ names = list(dict.fromkeys(names))
+ return names
+
+if __name__ == '__main__':
+ if len(argv)>1:
+ ports = argv[1].split(",")
+ services = get_services()
+
+ for port in ports:
+ if port and port[0] == '!':
+ port = port[1:]
+ if re.match('^[0-9]{1,5}-[0-9]{1,5}$', port):
+ port_1, port_2 = port.split('-')
+ if int(port_1) not in range(1, 65536) or int(port_2) not in range(1, 65536):
+ print(f'Error: {port} is not a valid port range')
+ exit(1)
+ if int(port_1) > int(port_2):
+ print(f'Error: {port} is not a valid port range')
+ exit(1)
+ elif port.isnumeric():
+ if int(port) not in range(1, 65536):
+ print(f'Error: {port} is not a valid port')
+ exit(1)
+ elif port not in services:
+ print(f'Error: {port} is not a valid service name')
+ exit(1)
+ else:
+ exit(2)
+
+ exit(0)
diff --git a/src/validators/port-range b/src/validators/port-range
new file mode 100644
index 0000000..526c639
--- /dev/null
+++ b/src/validators/port-range
@@ -0,0 +1,40 @@
+#!/usr/bin/python3
+
+import sys
+import re
+
+from vyos.utils.file import read_file
+
+services_file = '/etc/services'
+
+def get_services():
+ names = []
+ service_data = read_file(services_file, "")
+ for line in service_data.split("\n"):
+ if not line or line[0] == '#':
+ continue
+ names.append(line.split(None, 1)[0])
+ return names
+
+def error(port_range):
+ print(f'Error: {port_range} is not a valid port or port range')
+ sys.exit(1)
+
+if __name__ == '__main__':
+ if len(sys.argv)>1:
+ port_range = sys.argv[1]
+ if re.match('^[0-9]{1,5}-[0-9]{1,5}$', port_range):
+ port_1, port_2 = port_range.split('-')
+ if int(port_1) not in range(1, 65536) or int(port_2) not in range(1, 65536):
+ error(port_range)
+ if int(port_1) > int(port_2):
+ error(port_range)
+ elif port_range.isnumeric() and int(port_range) not in range(1, 65536):
+ error(port_range)
+ elif not port_range.isnumeric() and port_range not in get_services():
+ print(f'Error: {port_range} is not a valid service name')
+ sys.exit(1)
+ else:
+ sys.exit(2)
+
+ sys.exit(0)
diff --git a/src/validators/script b/src/validators/script
new file mode 100644
index 0000000..eb176d2
--- /dev/null
+++ b/src/validators/script
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018-2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import sys
+import shlex
+
+from vyos.utils.file import file_is_persistent
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ sys.exit('Please specify script file to check')
+
+ # if the "script" is a script+ stowaway arguments, this removes the aguements
+ script = shlex.split(sys.argv[1])[0]
+
+ if not os.path.exists(script):
+ sys.exit(f'File {script} does not exist')
+
+ if not (os.path.isfile(script) and os.access(script, os.X_OK)):
+ sys.exit(f'File {script} is not an executable file')
+
+ # File outside the config dir is just a warning
+ if not file_is_persistent(script):
+ sys.exit(0)(
+ f'Warning: file {script} is outside the "/config" directory\n'
+ 'It will not be automatically migrated to a new image on system update'
+ )
diff --git a/src/validators/sysctl b/src/validators/sysctl
new file mode 100644
index 0000000..9b5bba3
--- /dev/null
+++ b/src/validators/sysctl
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+declare -a array
+eval "array=($(/sbin/sysctl -N -a))"
+
+if [[ ! " ${array[@]} " =~ " $1 " ]]; then
+ # passed sysctl option is invalid
+ exit 1
+fi
+exit 0
diff --git a/src/validators/timezone b/src/validators/timezone
new file mode 100644
index 0000000..e55af8d
--- /dev/null
+++ b/src/validators/timezone
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019-2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import argparse
+import sys
+
+from vyos.utils.process import cmd
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--validate", action="store", required=True, help="Check if timezone is valid")
+ args = parser.parse_args()
+
+ tz_data = cmd('timedatectl list-timezones')
+ tz_data = tz_data.split('\n')
+
+ if args.validate not in tz_data:
+ sys.exit("the timezone can't be found in the timezone list")
+ sys.exit()
diff --git a/src/validators/vrf-name b/src/validators/vrf-name
new file mode 100644
index 0000000..29167c6
--- /dev/null
+++ b/src/validators/vrf-name
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+from sys import argv, exit
+
+if __name__ == '__main__':
+ if len(argv) != 2:
+ exit(1)
+
+ vrf = argv[1]
+ length = len(vrf)
+
+ if length not in range(1, 16):
+ exit(1)
+
+ # Treat loopback interface "lo" explicitly. Adding "lo" explicitly to the
+ # following regex pattern would deny any VRF name starting with lo - thuse
+ # local-vrf would be illegal - and that we do not want.
+ if vrf == "lo":
+ exit(1)
+
+ pattern = r'^(?!(bond|br|dum|eth|lan|eno|ens|enp|enx|gnv|ipoe|l2tp|l2tpeth|\
+ vtun|ppp|pppoe|peth|tun|vti|vxlan|wg|wlan|wwan|\d)\d*(\.\d+)?(v.+)?).*$'
+ if not re.match(pattern, vrf):
+ exit(1)
+
+ exit(0)
diff --git a/src/validators/wireless-phy b/src/validators/wireless-phy
new file mode 100644
index 0000000..513a902
--- /dev/null
+++ b/src/validators/wireless-phy
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) 2018-2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if [ ! -d /sys/class/ieee80211 ]; then
+ echo No IEEE 802.11 physical interfaces detected
+ exit 1
+fi
+
+if [ ! -e /sys/class/ieee80211/$1 ]; then
+ echo Device interface "$1" does not exist
+ exit 1
+fi