mirror of
https://github.com/Telecominfraproject/ols-ucentral-schema.git
synced 2025-10-29 17:22:23 +00:00
schema: introduce port-forward and traffic-allow firewall settings
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
committed by
John Crispin
parent
084b847b8a
commit
2bf1645d3a
@@ -65,6 +65,18 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Port forwardings are only supported on downstream interfaces
|
||||||
|
if ((interface.ipv4?.port_forward || interface.ipv6?.port_forward) && interface.role != 'downstream') {
|
||||||
|
warn("Port forwardings are only supported on downstream interfaces.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traffic accept rules are only supported on downstream interfaces
|
||||||
|
if (interface.ipv6?.traffic_allow && interface.role != 'downstream') {
|
||||||
|
warn("Traffic accept rules are only supported on downstream interfaces.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Gather related BSS modes and ethernet ports.
|
// Gather related BSS modes and ethernet ports.
|
||||||
let bss_modes = map(interface.ssids, ssid => ssid.bss_mode);
|
let bss_modes = map(interface.ssids, ssid => ssid.bss_mode);
|
||||||
let eth_ports = ethernet.lookup_by_interface_vlan(interface);
|
let eth_ports = ethernet.lookup_by_interface_vlan(interface);
|
||||||
|
|||||||
@@ -140,3 +140,32 @@ set firewall.@rule[-1].family='ipv6'
|
|||||||
set firewall.@rule[-1].proto='udp'
|
set firewall.@rule[-1].proto='udp'
|
||||||
set firewall.@rule[-1].target='ACCEPT'
|
set firewall.@rule[-1].target='ACCEPT'
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{%
|
||||||
|
for (let forward in interface.ipv4?.port_forward)
|
||||||
|
include('firewall/forward.uc', {
|
||||||
|
forward,
|
||||||
|
family: 'ipv4',
|
||||||
|
source_zone: ethernet.find_interface('upstream', interface.vlan?.id),
|
||||||
|
destination_zone: name,
|
||||||
|
destination_subnet: interface.ipv4.subnet
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let forward in interface.ipv6?.port_forward)
|
||||||
|
include('firewall/forward.uc', {
|
||||||
|
forward,
|
||||||
|
family: 'ipv6',
|
||||||
|
source_zone: ethernet.find_interface('upstream', interface.vlan?.id),
|
||||||
|
destination_zone: name,
|
||||||
|
destination_subnet: interface.ipv6.subnet
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let allow in interface.ipv6?.traffic_allow)
|
||||||
|
include('firewall/allow.uc', {
|
||||||
|
allow,
|
||||||
|
family: 'ipv6',
|
||||||
|
source_zone: ethernet.find_interface('upstream', interface.vlan?.id),
|
||||||
|
destination_zone: name,
|
||||||
|
destination_subnet: interface.ipv6.subnet
|
||||||
|
});
|
||||||
|
%}
|
||||||
|
|||||||
20
renderer/templates/interface/firewall/allow.uc
Normal file
20
renderer/templates/interface/firewall/allow.uc
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
add firewall rule
|
||||||
|
set firewall.@rule[-1].name='Allow traffic to {{ allow.destination_address }}'
|
||||||
|
set firewall.@rule[-1].family={{ s(family) }}
|
||||||
|
set firewall.@rule[-1].src={{ s(source_zone || '*') }}
|
||||||
|
set firewall.@rule[-1].dest={{ s(destination_zone) }}
|
||||||
|
{% for (let proto in ((allow.protocol in ['any', 'all', '*'] && (allow.source_ports || allow.destination_ports)) ? ['tcp', 'udp'] : [ allow.protocol ])): %}
|
||||||
|
add_list firewall.@rule[-1].proto={{ s(proto) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% if (allow.source_address): %}
|
||||||
|
set firewall.@rule[-1].src_ip={{ s(allow.source_address) }}
|
||||||
|
{% endif %}
|
||||||
|
{% for (let sport in allow.source_ports): %}
|
||||||
|
add_list firewall.@rule[-1].src_port={{ s(sport) }}
|
||||||
|
{% endfor %}
|
||||||
|
set firewall.@rule[-1].dest_ip={{ ipcalc.expand_wildcard_address(allow.destination_address, destination_subnet) }}
|
||||||
|
{% for (let dport in allow.destination_ports): %}
|
||||||
|
add_list firewall.@rule[-1].dest_port={{ s(dport) }}
|
||||||
|
{% endfor %}
|
||||||
|
set firewall.@rule[-1].target=ACCEPT
|
||||||
|
|
||||||
15
renderer/templates/interface/firewall/forward.uc
Normal file
15
renderer/templates/interface/firewall/forward.uc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% if (true || source_zone): %}
|
||||||
|
add firewall redirect
|
||||||
|
set firewall.@redirect[-1].name='Forward port {{ forward.external_port }} to {{ forward.internal_address }}'
|
||||||
|
set firewall.@redirect[-1].family={{ s(family) }}
|
||||||
|
set firewall.@redirect[-1].src={{ s(source_zone || '*') }}
|
||||||
|
set firewall.@redirect[-1].dest={{ s(destination_zone) }}
|
||||||
|
{% for (let proto in ((forward.protocol in ['any', 'all', '*']) ? ['tcp', 'udp'] : [ forward.protocol ])): %}
|
||||||
|
add_list firewall.@redirect[-1].proto={{ s(proto) }}
|
||||||
|
{% endfor %}
|
||||||
|
set firewall.@redirect[-1].src_dport={{ s(forward.external_port) }}
|
||||||
|
set firewall.@redirect[-1].dest_ip={{ ipcalc.expand_wildcard_address(forward.internal_address, destination_subnet) }}
|
||||||
|
set firewall.@redirect[-1].dest_port={{ s(forward.internal_port) }}
|
||||||
|
set firewall.@redirect[-1].target=DNAT
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
41
schema/interface.ipv4.port-forward.yml
Normal file
41
schema/interface.ipv4.port-forward.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
description:
|
||||||
|
This section describes an IPv4 port forwarding.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
protocol:
|
||||||
|
description:
|
||||||
|
The layer 3 protocol to match.
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- tcp
|
||||||
|
- udp
|
||||||
|
- any
|
||||||
|
default: any
|
||||||
|
external-port:
|
||||||
|
description:
|
||||||
|
The external port(s) to forward.
|
||||||
|
type:
|
||||||
|
- integer
|
||||||
|
- string
|
||||||
|
minimum: 0
|
||||||
|
maximum: 65535
|
||||||
|
format: uc-portrange
|
||||||
|
internal-address:
|
||||||
|
description:
|
||||||
|
The internal IP to forward to. The address will be masked and concatenated
|
||||||
|
with the effective interface subnet.
|
||||||
|
type: string
|
||||||
|
format: ipv4
|
||||||
|
example: '0.0.0.120'
|
||||||
|
internal-port:
|
||||||
|
description:
|
||||||
|
The internal port to forward to. Defaults to the external port if omitted.
|
||||||
|
type:
|
||||||
|
- integer
|
||||||
|
- string
|
||||||
|
minimum: 0
|
||||||
|
maximum: 65535
|
||||||
|
format: uc-portrange
|
||||||
|
required:
|
||||||
|
- external-port
|
||||||
|
- internal-address
|
||||||
@@ -52,3 +52,7 @@ properties:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "https://ucentral.io/schema/v1/interface/ipv4/dhcp-lease/"
|
$ref: "https://ucentral.io/schema/v1/interface/ipv4/dhcp-lease/"
|
||||||
|
port-forward:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "https://ucentral.io/schema/v1/interface/ipv4/port-forward/"
|
||||||
|
|||||||
41
schema/interface.ipv6.port-forward.yml
Normal file
41
schema/interface.ipv6.port-forward.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
description:
|
||||||
|
This section describes an IPv6 port forwarding.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
protocol:
|
||||||
|
description:
|
||||||
|
The layer 3 protocol to match.
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- tcp
|
||||||
|
- udp
|
||||||
|
- any
|
||||||
|
default: any
|
||||||
|
external-port:
|
||||||
|
description:
|
||||||
|
The external port(s) to forward.
|
||||||
|
type:
|
||||||
|
- integer
|
||||||
|
- string
|
||||||
|
minimum: 0
|
||||||
|
maximum: 65535
|
||||||
|
format: uc-portrange
|
||||||
|
internal-address:
|
||||||
|
description:
|
||||||
|
The internal IP to forward to. The address will be masked and concatenated
|
||||||
|
with the effective interface subnet.
|
||||||
|
type: string
|
||||||
|
format: ipv6
|
||||||
|
example: '::1234:abcd'
|
||||||
|
internal-port:
|
||||||
|
description:
|
||||||
|
The internal port to forward to. Defaults to the external port if omitted.
|
||||||
|
type:
|
||||||
|
- integer
|
||||||
|
- string
|
||||||
|
minimum: 0
|
||||||
|
maximum: 65535
|
||||||
|
format: uc-portrange
|
||||||
|
required:
|
||||||
|
- external-port
|
||||||
|
- internal-address
|
||||||
49
schema/interface.ipv6.traffic-allow.yml
Normal file
49
schema/interface.ipv6.traffic-allow.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
description:
|
||||||
|
This section describes an IPv6 traffic accept rule.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
protocol:
|
||||||
|
description:
|
||||||
|
The layer 3 protocol to match.
|
||||||
|
type: string
|
||||||
|
default: any
|
||||||
|
source-address:
|
||||||
|
description:
|
||||||
|
The source IP to allow traffic from.
|
||||||
|
type: string
|
||||||
|
format: uc-cidr6
|
||||||
|
example: 2001:db8:1234:abcd::/64
|
||||||
|
default: ::/0
|
||||||
|
source-ports:
|
||||||
|
description:
|
||||||
|
The source port(s) to accept.
|
||||||
|
type: array
|
||||||
|
minItems: 1
|
||||||
|
items:
|
||||||
|
type:
|
||||||
|
- integer
|
||||||
|
- string
|
||||||
|
minimum: 0
|
||||||
|
maximum: 65535
|
||||||
|
format: uc-portrange
|
||||||
|
destination-address:
|
||||||
|
description:
|
||||||
|
The destination IP to allow traffic to. The address will be masked and
|
||||||
|
concatenated with the effective interface subnet.
|
||||||
|
type: string
|
||||||
|
format: ipv6
|
||||||
|
example: ::1000
|
||||||
|
destination-ports:
|
||||||
|
description:
|
||||||
|
The destination ports to accept.
|
||||||
|
type: array
|
||||||
|
minItems: 1
|
||||||
|
items:
|
||||||
|
type:
|
||||||
|
- integer
|
||||||
|
- string
|
||||||
|
minimum: 0
|
||||||
|
maximum: 65535
|
||||||
|
format: uc-portrange
|
||||||
|
required:
|
||||||
|
- destination-address
|
||||||
@@ -50,3 +50,11 @@ properties:
|
|||||||
minimum: 0
|
minimum: 0
|
||||||
dhcpv6:
|
dhcpv6:
|
||||||
$ref: "https://ucentral.io/schema/v1/interface/ipv6/dhcpv6/"
|
$ref: "https://ucentral.io/schema/v1/interface/ipv6/dhcpv6/"
|
||||||
|
port-forward:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "https://ucentral.io/schema/v1/interface/ipv6/port-forward/"
|
||||||
|
traffic-allow:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "https://ucentral.io/schema/v1/interface/ipv6/traffic-allow/"
|
||||||
|
|||||||
409
schemareader.uc
409
schemareader.uc
@@ -37,6 +37,13 @@ function matchUcBase64(value) {
|
|||||||
return b64dec(value) != null;
|
return b64dec(value) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function matchUcPortrange(value) {
|
||||||
|
let ports = match(value, /^([0-9]|[1-9][0-9]*)(-([0-9]|[1-9][0-9]*))?$/);
|
||||||
|
if (!ports) return false;
|
||||||
|
let min = +ports[1], max = ports[2] ? +ports[3] : min;
|
||||||
|
return (min <= 65535 && max <= 65535 && max >= min);
|
||||||
|
}
|
||||||
|
|
||||||
function matchHostname(value) {
|
function matchHostname(value) {
|
||||||
if (length(value) > 255) return false;
|
if (length(value) > 255) return false;
|
||||||
let labels = split(value, ".");
|
let labels = split(value, ".");
|
||||||
@@ -1457,6 +1464,111 @@ function instantiateInterfaceIpv4DhcpLease(location, value, errors) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function instantiateInterfaceIpv4PortForward(location, value, errors) {
|
||||||
|
if (type(value) == "object") {
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
function parseProtocol(location, value, errors) {
|
||||||
|
if (type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type string" ]);
|
||||||
|
|
||||||
|
if (!(value in [ "tcp", "udp", "any" ]))
|
||||||
|
push(errors, [ location, "must be one of \"tcp\", \"udp\" or \"any\"" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "protocol")) {
|
||||||
|
obj.protocol = parseProtocol(location + "/protocol", value["protocol"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj.protocol = "any";
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseExternalPort(location, value, errors) {
|
||||||
|
if (type(value) in [ "int", "double" ]) {
|
||||||
|
if (value > 65535)
|
||||||
|
push(errors, [ location, "must be lower than or equal to 65535" ]);
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
push(errors, [ location, "must be bigger than or equal to 0" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchUcPortrange(value))
|
||||||
|
push(errors, [ location, "must be a valid network port range" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "int" && type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type integer or string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "external-port")) {
|
||||||
|
obj.external_port = parseExternalPort(location + "/external-port", value["external-port"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
push(errors, [ location, "is required" ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseInternalAddress(location, value, errors) {
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchIpv4(value))
|
||||||
|
push(errors, [ location, "must be a valid IPv4 address" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "internal-address")) {
|
||||||
|
obj.internal_address = parseInternalAddress(location + "/internal-address", value["internal-address"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
push(errors, [ location, "is required" ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseInternalPort(location, value, errors) {
|
||||||
|
if (type(value) in [ "int", "double" ]) {
|
||||||
|
if (value > 65535)
|
||||||
|
push(errors, [ location, "must be lower than or equal to 65535" ]);
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
push(errors, [ location, "must be bigger than or equal to 0" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchUcPortrange(value))
|
||||||
|
push(errors, [ location, "must be a valid network port range" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "int" && type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type integer or string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "internal-port")) {
|
||||||
|
obj.internal_port = parseInternalPort(location + "/internal-port", value["internal-port"], errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "object")
|
||||||
|
push(errors, [ location, "must be of type object" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
function instantiateInterfaceIpv4(location, value, errors) {
|
function instantiateInterfaceIpv4(location, value, errors) {
|
||||||
if (type(value) == "object") {
|
if (type(value) == "object") {
|
||||||
let obj = {};
|
let obj = {};
|
||||||
@@ -1570,6 +1682,21 @@ function instantiateInterfaceIpv4(location, value, errors) {
|
|||||||
obj.dhcp_leases = parseDhcpLeases(location + "/dhcp-leases", value["dhcp-leases"], errors);
|
obj.dhcp_leases = parseDhcpLeases(location + "/dhcp-leases", value["dhcp-leases"], errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parsePortForward(location, value, errors) {
|
||||||
|
if (type(value) == "array") {
|
||||||
|
return map(value, (item, i) => instantiateInterfaceIpv4PortForward(location + "/" + i, item, errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "array")
|
||||||
|
push(errors, [ location, "must be of type array" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "port-forward")) {
|
||||||
|
obj.port_forward = parsePortForward(location + "/port-forward", value["port-forward"], errors);
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1654,6 +1781,258 @@ function instantiateInterfaceIpv6Dhcpv6(location, value, errors) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function instantiateInterfaceIpv6PortForward(location, value, errors) {
|
||||||
|
if (type(value) == "object") {
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
function parseProtocol(location, value, errors) {
|
||||||
|
if (type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type string" ]);
|
||||||
|
|
||||||
|
if (!(value in [ "tcp", "udp", "any" ]))
|
||||||
|
push(errors, [ location, "must be one of \"tcp\", \"udp\" or \"any\"" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "protocol")) {
|
||||||
|
obj.protocol = parseProtocol(location + "/protocol", value["protocol"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj.protocol = "any";
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseExternalPort(location, value, errors) {
|
||||||
|
if (type(value) in [ "int", "double" ]) {
|
||||||
|
if (value > 65535)
|
||||||
|
push(errors, [ location, "must be lower than or equal to 65535" ]);
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
push(errors, [ location, "must be bigger than or equal to 0" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchUcPortrange(value))
|
||||||
|
push(errors, [ location, "must be a valid network port range" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "int" && type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type integer or string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "external-port")) {
|
||||||
|
obj.external_port = parseExternalPort(location + "/external-port", value["external-port"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
push(errors, [ location, "is required" ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseInternalAddress(location, value, errors) {
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchIpv6(value))
|
||||||
|
push(errors, [ location, "must be a valid IPv6 address" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "internal-address")) {
|
||||||
|
obj.internal_address = parseInternalAddress(location + "/internal-address", value["internal-address"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
push(errors, [ location, "is required" ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseInternalPort(location, value, errors) {
|
||||||
|
if (type(value) in [ "int", "double" ]) {
|
||||||
|
if (value > 65535)
|
||||||
|
push(errors, [ location, "must be lower than or equal to 65535" ]);
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
push(errors, [ location, "must be bigger than or equal to 0" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchUcPortrange(value))
|
||||||
|
push(errors, [ location, "must be a valid network port range" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "int" && type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type integer or string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "internal-port")) {
|
||||||
|
obj.internal_port = parseInternalPort(location + "/internal-port", value["internal-port"], errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "object")
|
||||||
|
push(errors, [ location, "must be of type object" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function instantiateInterfaceIpv6TrafficAllow(location, value, errors) {
|
||||||
|
if (type(value) == "object") {
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
function parseProtocol(location, value, errors) {
|
||||||
|
if (type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "protocol")) {
|
||||||
|
obj.protocol = parseProtocol(location + "/protocol", value["protocol"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj.protocol = "any";
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSourceAddress(location, value, errors) {
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchUcCidr6(value))
|
||||||
|
push(errors, [ location, "must be a valid IPv6 CIDR" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "source-address")) {
|
||||||
|
obj.source_address = parseSourceAddress(location + "/source-address", value["source-address"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj.source_address = "::/0";
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSourcePorts(location, value, errors) {
|
||||||
|
if (type(value) == "array") {
|
||||||
|
if (length(value) < 1)
|
||||||
|
push(errors, [ location, "must have at least 1 items" ]);
|
||||||
|
|
||||||
|
function parseItem(location, value, errors) {
|
||||||
|
if (type(value) in [ "int", "double" ]) {
|
||||||
|
if (value > 65535)
|
||||||
|
push(errors, [ location, "must be lower than or equal to 65535" ]);
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
push(errors, [ location, "must be bigger than or equal to 0" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchUcPortrange(value))
|
||||||
|
push(errors, [ location, "must be a valid network port range" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "int" && type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type integer or string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return map(value, (item, i) => parseItem(location + "/" + i, item, errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "array")
|
||||||
|
push(errors, [ location, "must be of type array" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "source-ports")) {
|
||||||
|
obj.source_ports = parseSourcePorts(location + "/source-ports", value["source-ports"], errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDestinationAddress(location, value, errors) {
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchIpv6(value))
|
||||||
|
push(errors, [ location, "must be a valid IPv6 address" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "destination-address")) {
|
||||||
|
obj.destination_address = parseDestinationAddress(location + "/destination-address", value["destination-address"], errors);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
push(errors, [ location, "is required" ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDestinationPorts(location, value, errors) {
|
||||||
|
if (type(value) == "array") {
|
||||||
|
if (length(value) < 1)
|
||||||
|
push(errors, [ location, "must have at least 1 items" ]);
|
||||||
|
|
||||||
|
function parseItem(location, value, errors) {
|
||||||
|
if (type(value) in [ "int", "double" ]) {
|
||||||
|
if (value > 65535)
|
||||||
|
push(errors, [ location, "must be lower than or equal to 65535" ]);
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
push(errors, [ location, "must be bigger than or equal to 0" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) == "string") {
|
||||||
|
if (!matchUcPortrange(value))
|
||||||
|
push(errors, [ location, "must be a valid network port range" ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "int" && type(value) != "string")
|
||||||
|
push(errors, [ location, "must be of type integer or string" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return map(value, (item, i) => parseItem(location + "/" + i, item, errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "array")
|
||||||
|
push(errors, [ location, "must be of type array" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "destination-ports")) {
|
||||||
|
obj.destination_ports = parseDestinationPorts(location + "/destination-ports", value["destination-ports"], errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "object")
|
||||||
|
push(errors, [ location, "must be of type object" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
function instantiateInterfaceIpv6(location, value, errors) {
|
function instantiateInterfaceIpv6(location, value, errors) {
|
||||||
if (type(value) == "object") {
|
if (type(value) == "object") {
|
||||||
let obj = {};
|
let obj = {};
|
||||||
@@ -1730,6 +2109,36 @@ function instantiateInterfaceIpv6(location, value, errors) {
|
|||||||
obj.dhcpv6 = instantiateInterfaceIpv6Dhcpv6(location + "/dhcpv6", value["dhcpv6"], errors);
|
obj.dhcpv6 = instantiateInterfaceIpv6Dhcpv6(location + "/dhcpv6", value["dhcpv6"], errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parsePortForward(location, value, errors) {
|
||||||
|
if (type(value) == "array") {
|
||||||
|
return map(value, (item, i) => instantiateInterfaceIpv6PortForward(location + "/" + i, item, errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "array")
|
||||||
|
push(errors, [ location, "must be of type array" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "port-forward")) {
|
||||||
|
obj.port_forward = parsePortForward(location + "/port-forward", value["port-forward"], errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseTrafficAllow(location, value, errors) {
|
||||||
|
if (type(value) == "array") {
|
||||||
|
return map(value, (item, i) => instantiateInterfaceIpv6TrafficAllow(location + "/" + i, item, errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type(value) != "array")
|
||||||
|
push(errors, [ location, "must be of type array" ]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists(value, "traffic-allow")) {
|
||||||
|
obj.traffic_allow = parseTrafficAllow(location + "/traffic-allow", value["traffic-allow"], errors);
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -652,6 +652,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"interface.ipv4.port-forward": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"protocol": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"tcp",
|
||||||
|
"udp",
|
||||||
|
"any"
|
||||||
|
],
|
||||||
|
"default": "any"
|
||||||
|
},
|
||||||
|
"external-port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 65535,
|
||||||
|
"format": "uc-portrange"
|
||||||
|
},
|
||||||
|
"internal-address": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv4",
|
||||||
|
"example": "0.0.0.120"
|
||||||
|
},
|
||||||
|
"internal-port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 65535,
|
||||||
|
"format": "uc-portrange"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"external-port",
|
||||||
|
"internal-address"
|
||||||
|
]
|
||||||
|
},
|
||||||
"interface.ipv4": {
|
"interface.ipv4": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -705,6 +746,12 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/$defs/interface.ipv4.dhcp-lease"
|
"$ref": "#/$defs/interface.ipv4.dhcp-lease"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"port-forward": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/interface.ipv4.port-forward"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -734,6 +781,96 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"interface.ipv6.port-forward": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"protocol": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"tcp",
|
||||||
|
"udp",
|
||||||
|
"any"
|
||||||
|
],
|
||||||
|
"default": "any"
|
||||||
|
},
|
||||||
|
"external-port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 65535,
|
||||||
|
"format": "uc-portrange"
|
||||||
|
},
|
||||||
|
"internal-address": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv6",
|
||||||
|
"example": "::1234:abcd"
|
||||||
|
},
|
||||||
|
"internal-port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 65535,
|
||||||
|
"format": "uc-portrange"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"external-port",
|
||||||
|
"internal-address"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"interface.ipv6.traffic-allow": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"protocol": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "any"
|
||||||
|
},
|
||||||
|
"source-address": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uc-cidr6",
|
||||||
|
"example": "2001:db8:1234:abcd::/64",
|
||||||
|
"default": "::/0"
|
||||||
|
},
|
||||||
|
"source-ports": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 65535,
|
||||||
|
"format": "uc-portrange"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"destination-address": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv6",
|
||||||
|
"example": "::1000"
|
||||||
|
},
|
||||||
|
"destination-ports": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 65535,
|
||||||
|
"format": "uc-portrange"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"destination-address"
|
||||||
|
]
|
||||||
|
},
|
||||||
"interface.ipv6": {
|
"interface.ipv6": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -765,6 +902,18 @@
|
|||||||
},
|
},
|
||||||
"dhcpv6": {
|
"dhcpv6": {
|
||||||
"$ref": "#/$defs/interface.ipv6.dhcpv6"
|
"$ref": "#/$defs/interface.ipv6.dhcpv6"
|
||||||
|
},
|
||||||
|
"port-forward": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/interface.ipv6.port-forward"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"traffic-allow": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/interface.ipv6.traffic-allow"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user