mirror of
https://github.com/Telecominfraproject/ols-ucentral-schema.git
synced 2025-10-29 09:12:20 +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;
|
||||
}
|
||||
|
||||
// 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.
|
||||
let bss_modes = map(interface.ssids, ssid => ssid.bss_mode);
|
||||
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].target='ACCEPT'
|
||||
{% 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
|
||||
items:
|
||||
$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
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (length(value) > 255) return false;
|
||||
let labels = split(value, ".");
|
||||
@@ -1457,6 +1464,111 @@ function instantiateInterfaceIpv4DhcpLease(location, value, errors) {
|
||||
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) {
|
||||
if (type(value) == "object") {
|
||||
let obj = {};
|
||||
@@ -1570,6 +1682,21 @@ function instantiateInterfaceIpv4(location, value, 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;
|
||||
}
|
||||
|
||||
@@ -1654,6 +1781,258 @@ function instantiateInterfaceIpv6Dhcpv6(location, value, errors) {
|
||||
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) {
|
||||
if (type(value) == "object") {
|
||||
let obj = {};
|
||||
@@ -1730,6 +2109,36 @@ function instantiateInterfaceIpv6(location, value, 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -705,6 +746,12 @@
|
||||
"items": {
|
||||
"$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": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -765,6 +902,18 @@
|
||||
},
|
||||
"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