diff --git a/renderer/templates/interface/dhcp.uc b/renderer/templates/interface/dhcp.uc index 788a657..4be4ecd 100644 --- a/renderer/templates/interface/dhcp.uc +++ b/renderer/templates/interface/dhcp.uc @@ -1,7 +1,16 @@ {% let name = ethernet.calculate_name(interface) %} {% let dhcp = ipv4.dhcp || { ignore: 1 } %} {% let dhcpv6 = ipv6.dhcpv6 || {} %} - +{% function use_dns() { + let ret = ''; + if (type(dhcp.use_dns) == 'array') { + for (let k, v in dhcp.use_dns) + ret += ',' + v; + } else { + ret += ',' + dhcp.use_dns; + } + return ret; +} %} set dhcp.{{ name }}=dhcp set dhcp.{{ name }}.interface={{ s(ethernet.calculate_ipv4_name(interface)) }} set dhcp.{{ name }}.start={{ dhcp.lease_first }} @@ -9,7 +18,7 @@ set dhcp.{{ name }}.limit={{ dhcp.lease_count }} set dhcp.{{ name }}.leasetime={{ dhcp.lease_time }} set dhcp.{{ name }}.ignore={{ b(dhcp.ignore) }} {% if (dhcp.use_dns): %} -add_list dhcp.{{ name }}.dhcp_option='6,{{ dhcp.use_dns }}' +add_list dhcp.{{ name }}.dhcp_option='6{{ use_dns() }}' {% endif %} {% if (interface.role != 'upstream'): %} {% if (dhcpv6.mode == 'hybrid'): %} diff --git a/schema/interface.ipv4.dhcp.yml b/schema/interface.ipv4.dhcp.yml index 0ac46c1..844b951 100644 --- a/schema/interface.ipv4.dhcp.yml +++ b/schema/interface.ipv4.dhcp.yml @@ -23,5 +23,10 @@ properties: use-dns: description: The DNS server sent to clients as DHCP option 6. - type: string - format: uc-ip + anyOf: + - type: string + format: ipv4 + - type: array + items: + type: string + format: ipv4 diff --git a/schemareader.uc b/schemareader.uc index 8520d34..9b481c8 100644 --- a/schemareader.uc +++ b/schemareader.uc @@ -1472,14 +1472,82 @@ function instantiateInterfaceIpv4Dhcp(location, value, errors) { } function parseUseDns(location, value, errors) { - if (type(value) == "string") { - if (!matchUcIp(value)) - push(errors, [ location, "must be a valid IPv4 or IPv6 address" ]); + function parseVariant0(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 (type(value) != "string") - push(errors, [ location, "must be of type string" ]); + function parseVariant1(location, value, errors) { + if (type(value) == "array") { + function parseItem(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; + } + + return map(value, (item, i) => parseItem(location + "/" + i, item, errors)); + } + + if (type(value) != "array") + push(errors, [ location, "must be of type array" ]); + + return value; + } + + let success = 0, tryval, tryerr, vvalue = null, verrors = []; + + tryerr = []; + tryval = parseVariant0(location, value, tryerr); + if (!length(tryerr)) { + if (type(vvalue) == "object" && type(tryval) == "object") + vvalue = { ...vvalue, ...tryval }; + else + vvalue = tryval; + + success++; + } + else { + push(verrors, join(" and\n", map(tryerr, err => "\t - " + err[1]))); + } + + tryerr = []; + tryval = parseVariant1(location, value, tryerr); + if (!length(tryerr)) { + if (type(vvalue) == "object" && type(tryval) == "object") + vvalue = { ...vvalue, ...tryval }; + else + vvalue = tryval; + + success++; + } + else { + push(verrors, join(" and\n", map(tryerr, err => "\t - " + err[1]))); + } + + if (success == 0) { + if (length(verrors)) + push(errors, [ location, "must match at least one of the following constraints:\n" + join("\n- or -\n", verrors) ]); + else + push(errors, [ location, "must match only one variant" ]); + return null; + } + + value = vvalue; return value; } diff --git a/ucentral.schema.full.json b/ucentral.schema.full.json index aaf78d0..310b942 100644 --- a/ucentral.schema.full.json +++ b/ucentral.schema.full.json @@ -1042,8 +1042,19 @@ }, "use-dns": { "description": "The DNS server sent to clients as DHCP option 6.", - "type": "string", - "format": "uc-ip" + "anyOf": [ + { + "type": "string", + "format": "ipv4" + }, + { + "type": "array", + "items": { + "type": "string", + "format": "ipv4" + } + } + ] } } }, diff --git a/ucentral.schema.json b/ucentral.schema.json index a9a4d2c..98e97a2 100644 --- a/ucentral.schema.json +++ b/ucentral.schema.json @@ -671,8 +671,19 @@ "default": "6h" }, "use-dns": { - "type": "string", - "format": "uc-ip" + "anyOf": [ + { + "type": "string", + "format": "ipv4" + }, + { + "type": "array", + "items": { + "type": "string", + "format": "ipv4" + } + } + ] } } }, diff --git a/ucentral.schema.pretty.json b/ucentral.schema.pretty.json index 3d51f22..463c5b5 100644 --- a/ucentral.schema.pretty.json +++ b/ucentral.schema.pretty.json @@ -753,8 +753,19 @@ }, "use-dns": { "description": "The DNS server sent to clients as DHCP option 6.", - "type": "string", - "format": "uc-ip" + "anyOf": [ + { + "type": "string", + "format": "ipv4" + }, + { + "type": "array", + "items": { + "type": "string", + "format": "ipv4" + } + } + ] } } },