From 3b6591fd9590426164b84cf8470d1d625155f2c8 Mon Sep 17 00:00:00 2001 From: Paul Dee Date: Thu, 16 Mar 2023 19:04:20 +0100 Subject: [PATCH] NEW FEATURE: Support DNS LOC record type (#2174) --- build/generate/featureMatrix.go | 6 + commands/types/dnscontrol.d.ts | 225 ++++++++++ documentation/functions/domain/LOC.md | 103 +++++ .../functions/record/LOC_BUILDER_DD.md | 68 +++ .../functions/record/LOC_BUILDER_DMM_STR.md | 49 +++ .../functions/record/LOC_BUILDER_DMS_STR.md | 50 +++ .../functions/record/LOC_BUILDER_STRING.md | 57 +++ documentation/providers.md | 94 ++--- integrationTest/integration_test.go | 26 ++ models/dnsrr.go | 2 + models/record.go | 28 ++ models/t_loc.go | 187 +++++++++ models/t_parse.go | 2 + pkg/js/helpers.js | 386 ++++++++++++++++++ pkg/js/parse_tests/045-loc.js | 79 ++++ pkg/js/parse_tests/045-loc.json | 160 ++++++++ pkg/js/parse_tests/045-loc/foo.com.zone | 18 + pkg/normalize/validate.go | 5 + .../akamaiedgedns/akamaiEdgeDnsProvider.go | 1 + providers/axfrddns/axfrddnsProvider.go | 1 + providers/azuredns/azureDnsProvider.go | 1 + providers/bind/bindProvider.go | 1 + providers/capabilities.go | 3 + providers/capability_string.go | 27 +- providers/cloudflare/cloudflareProvider.go | 1 + providers/cloudns/cloudnsProvider.go | 1 + providers/desec/desecProvider.go | 1 + .../digitalocean/digitaloceanProvider.go | 1 + providers/dnsimple/dnsimpleProvider.go | 1 + providers/dnsmadeeasy/dnsMadeEasyProvider.go | 1 + .../domainnameshop/domainnameshopProvider.go | 5 +- providers/exoscale/exoscaleProvider.go | 1 + providers/gandiv5/gandi_v5Provider.go | 1 + providers/gcloud/gcloudProvider.go | 1 + providers/gcore/gcoreProvider.go | 1 + providers/hedns/hednsProvider.go | 1 + providers/hetzner/hetznerProvider.go | 1 + providers/hostingde/hostingdeProvider.go | 1 + providers/inwx/inwxProvider.go | 1 + providers/linode/linodeProvider.go | 1 + providers/loopia/loopiaProvider.go | 1 + providers/luadns/luadnsProvider.go | 1 + providers/msdns/msdnsProvider.go | 1 + providers/namecheap/namecheapProvider.go | 1 + providers/namedotcom/namedotcomProvider.go | 1 + providers/netcup/netcupProvider.go | 1 + providers/netlify/netlifyProvider.go | 1 + providers/ns1/ns1Provider.go | 1 + providers/oracle/oracleProvider.go | 1 + providers/ovh/ovhProvider.go | 1 + providers/porkbun/porkbunProvider.go | 1 + providers/powerdns/powerdnsProvider.go | 1 + providers/route53/route53Provider.go | 1 + providers/rwth/rwthProvider.go | 1 + providers/softlayer/softlayerProvider.go | 1 + providers/transip/transipProvider.go | 1 + providers/vultr/vultrProvider.go | 1 + 57 files changed, 1554 insertions(+), 62 deletions(-) create mode 100644 documentation/functions/domain/LOC.md create mode 100644 documentation/functions/record/LOC_BUILDER_DD.md create mode 100644 documentation/functions/record/LOC_BUILDER_DMM_STR.md create mode 100644 documentation/functions/record/LOC_BUILDER_DMS_STR.md create mode 100644 documentation/functions/record/LOC_BUILDER_STRING.md create mode 100644 models/t_loc.go create mode 100644 pkg/js/parse_tests/045-loc.js create mode 100644 pkg/js/parse_tests/045-loc.json create mode 100644 pkg/js/parse_tests/045-loc/foo.com.zone diff --git a/build/generate/featureMatrix.go b/build/generate/featureMatrix.go index bce608c8b..8d1361818 100644 --- a/build/generate/featureMatrix.go +++ b/build/generate/featureMatrix.go @@ -79,6 +79,7 @@ func matrixData() *FeatureMatrix { DomainModifierAlias = "ALIAS" DomainModifierDnssec = "AUTODNSSEC" DomainModifierCaa = "CAA" + DomainModifierLoc = "LOC" DomainModifierPtr = "PTR" DomainModifierNaptr = "NAPTR" DomainModifierSoa = "SOA" @@ -101,6 +102,7 @@ func matrixData() *FeatureMatrix { DomainModifierAlias, DomainModifierDnssec, DomainModifierCaa, + DomainModifierLoc, DomainModifierPtr, DomainModifierNaptr, DomainModifierSoa, @@ -182,6 +184,10 @@ func matrixData() *FeatureMatrix { DomainModifierDs, providers.CanUseDS, ) + setCapability( + DomainModifierLoc, + providers.CanUseLOC, + ) setCapability( DomainModifierNaptr, providers.CanUseNAPTR, diff --git a/commands/types/dnscontrol.d.ts b/commands/types/dnscontrol.d.ts index e483007fe..022659196 100644 --- a/commands/types/dnscontrol.d.ts +++ b/commands/types/dnscontrol.d.ts @@ -684,6 +684,60 @@ declare function IGNORE_TARGET(pattern: string, rType: string): DomainModifier; */ declare function INCLUDE(domain: string): DomainModifier; +/** + * ## Description ## + * + * Strictly follows [RFC 1876](https://datatracker.ietf.org/doc/html/rfc1876). + * + * Fairly intuitive. + * + * There are some behaviours that you should be aware of, however: + * + * > If omitted, minutes and seconds default to zero, size defaults to 1m, + * horizontal precision defaults to 10000m, and vertical precision + * defaults to 10m. These defaults are chosen to represent typical + * ZIP/postal code area sizes, since it is often easy to find + * approximate geographical location by ZIP/postal code. + * + * Alas, the world does not revolve around US ZIP codes, but here we are. Internally, + * the LOC record type will supply defaults where values were absent on DNS import. + * One must supply the `LOC()` js helper all parameters. If that seems like too + * much work, see also helper functions: + * + * * [`LOC_BUILDER_DD()`](../record/LOC_BUILDER_DD.md) - build a `LOC` by supplying only **d**ecimal **d**egrees. + * * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() + * + * ## Format ## + * + * The coordinate format for `LOC()` is: + * + * `degrees,minutes,seconds,[NnSs],deg,min,sec,[EeWw],altitude,size,horizontal_precision,vertical_precision` + * + * ## Examples ## + * + * ```javascript + * D("foo.com","none" + * // LOC "subdomain", d1, m1, s1, "[NnSs]", d2, m2, s2, "[EeWw]", alt, siz, hp, vp) + * //42 21 54 N 71 06 18 W -24m 30m + * , LOC("@", 42, 21, 54, "N", 71, 6, 18, "W", -24, 30, 0, 0) + * //42 21 43.952 N 71 5 6.344 W -24m 1m 200m 10m + * , LOC("a", 42, 21, 43.952, "N", 71, 5, 6.344, "W", -24, 1, 200, 10) + * //52 14 05 N 00 08 50 E 10m + * , LOC("b", 52, 14, 5, "N", 0, 8, 50, "E", 10, 0, 0, 0) + * //32 7 19 S 116 2 25 E 10m + * , LOC("c", 32, 7, 19, "S",116, 2, 25, "E", 10, 0, 0, 0) + * //42 21 28.764 N 71 00 51.617 W -44m 2000m + * , LOC("d", 42, 21, 28.764, "N", 71, 0, 51.617, "W", -44, 2000, 0, 0) + * ); + * + * ``` + * + * @see https://dnscontrol.org/js#LOC + */ +declare function LOC(deg1: uint32, min1: uint32, sec1: float32, deg2: uint32, min2: uint32, sec2: float32, altitude: uint32, size: float32, horizontal_precision: float32, vertical_precision: float32): DomainModifier; + /** * MX adds an MX record to the domain. * @@ -2122,6 +2176,177 @@ declare function CAA_BUILDER(opts: { label?: string; iodef: string; iodef_critic */ declare function DMARC_BUILDER(opts: { label?: string; version?: string; policy: 'none' | 'quarantine' | 'reject'; subdomainPolicy?: 'none' | 'quarantine' | 'reject'; alignmentSPF?: 'strict' | 's' | 'relaxed' | 'r'; alignmentDKIM?: 'strict' | 's' | 'relaxed' | 'r'; percent?: number; rua?: string[]; ruf?: string[]; failureOptions?: { SPF: boolean, DKIM: boolean } | string; failureFormat?: string; reportInterval?: Duration; ttl?: Duration }): RecordModifier; +/** + * `LOC_BUILDER_DD({})` actually takes an object with the mentioned properties. + * + * A helper to build [`LOC`](../domain/LOC.md) records. Supply four parameters instead of 12. + * + * Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + * + * The cartesian coordinates are decimal degrees, like you typically find in e.g. Google Maps. + * + * Examples. + * + * Big Ben: + * `51.50084265331501, -0.12462541415599787` + * + * The White House: + * `38.89775977858357, -77.03655125982903` + * + * ```javascript + * D("example.com","none" + * , LOC_BUILDER_DD({ + * label: "big-ben", + * x: 51.50084265331501, + * y: -0.12462541415599787, + * alt: 6, + * }) + * , LOC_BUILDER_DD({ + * label: "white-house", + * x: 38.89775977858357, + * y: -77.03655125982903, + * alt: 19, + * }) + * , LOC_BUILDER_DD({ + * label: "white-house-ttl", + * x: 38.89775977858357, + * y: -77.03655125982903, + * alt: 19, + * ttl: "5m", + * }) + * ); + * + * ``` + * + * Part of the series: + * * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() + * + * @see https://dnscontrol.org/js#LOC_BUILDER_DD + */ +declare function LOC_BUILDER_DD(subdomain: string, decimal_degrees_x: float32, decimal_degrees_y: float32, altitude: float32, ttl: int): RecordModifier; + +/** + * `LOC_BUILDER_DMM({})` actually takes an object with the mentioned properties. + * + * A helper to build [`LOC`](../domain/LOC.md) records. Supply three parameters instead of 12. + * + * Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + * + * Accepts a string with decimal minutes (DMM) coordinates in the form: 25.24°S 153.15°E + * + * Note that the following are acceptable forms (symbols differ): + * * `25.24°S 153.15°E` + * * `25.24 S 153.15 E` + * * `25.24° S 153.15° E` + * * `25.24S 153.15E` + * + * ```javascript + * D("example.com","none" + * LOC_BUILDER_STR({ + * label: "tasmania", + * str: '42°S 147°E', + * alt: 3, + * }) + * ); + * + * ``` + * + * Part of the series: + * * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() + * + * @see https://dnscontrol.org/js#LOC_BUILDER_DMM + */ +declare function LOC_BUILDER_DMM(subdomain: string, input_string: string, altitude: float32, ttl: int): RecordModifier; + +/** + * `LOC_BUILDER_DMS_STR({})` actually takes an object with the mentioned properties. + * + * A helper to build [`LOC`](../domain/LOC.md) records. Supply three parameters instead of 12. + * + * Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + * + * Accepts a string with degrees, minutes, and seconds (DMS) coordinates in the form: 41°24'12.2"N 2°10'26.5"E + * + * Note that the following are acceptable forms (symbols differ): + * * `33°51′31″S 151°12′51″E` + * * `33°51'31"S 151°12'51"E` + * * `33d51m31sS 151d12m51sE` + * * `33d51m31s S 151d12m51s E` + * + * ```javascript + * D("example.com","none" + * LOC_BUILDER_DMS_STR({ + * label: "sydney-opera-house", + * str: '33°51′31″S 151°12′51″E', + * alt: 4, + * ttl: "5m", + * }) + * ); + * + * ``` + * + * Part of the series: + * * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() + * + * @see https://dnscontrol.org/js#LOC_BUILDER_DMS_STR + */ +declare function LOC_BUILDER_DMS_STR(subdomain: string, input_string: string, altitude: float32, ttl: int): RecordModifier; + +/** + * `LOC_BUILDER_STR({})` actually takes an object with the mentioned properties. + * + * A helper to build [`LOC`](../domain/LOC.md) records. Supply three parameters instead of 12. + * + * Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + * + * Accepts a string and tries all `LOC_BUILDER_DM*_STR({})` methods: + * * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * + * ```javascript + * D("example.com","none" + * , LOC_BUILDER_STR({ + * label: "old-faithful", + * str: '44.46046°N 110.82815°W', + * alt: 2240, + * }) + * , LOC_BUILDER_STR({ + * label: "ribblehead-viaduct", + * str: '54.210436°N 2.370231°W', + * alt: 300, + * }) + * , LOC_BUILDER_STR({ + * label: "guinness-brewery", + * str: '53°20′40″N 6°17′20″W', + * alt: 300, + * }) + * ); + * + * ``` + * + * Part of the series: + * * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() + * + * @see https://dnscontrol.org/js#LOC_BUILDER_STR + */ +declare function LOC_BUILDER_STR(subdomain: string, input_string: string, altitude: float32, ttl: int): RecordModifier; + /** * R53_ZONE lets you specify the AWS Zone ID for an entire domain (D()) or a specific R53_ALIAS() record. * diff --git a/documentation/functions/domain/LOC.md b/documentation/functions/domain/LOC.md new file mode 100644 index 000000000..4a77c2235 --- /dev/null +++ b/documentation/functions/domain/LOC.md @@ -0,0 +1,103 @@ +--- +name: LOC +parameters: + - deg1 + - min1 + - sec1 + - deg2 + - min2 + - sec2 + - altitude + - size + - horizontal_precision + - vertical_precision +parameter_types: + name: string + target: string + deg1: uint32 + min1: uint32 + sec1: float32 + deg2: uint32 + min2: uint32 + sec2: float32 + altitude: uint32 + size: float32 + horizontal_precision: float32 + vertical_precision: float32 +--- + +## Description ## + +Strictly follows [RFC 1876](https://datatracker.ietf.org/doc/html/rfc1876). + +A LOC record holds a geographical position. In the zone file, it may look like: + +```text +; +pipex.net. LOC 52 14 05 N 00 08 50 E 10m +``` + +On the wire, it is in a binary format. + +A use case for LOC is suggested in the RFC: + +> Some uses for the LOC RR have already been suggested, including the + USENET backbone flow maps, a "visual traceroute" application showing + the geographical path of an IP packet, and network management + applications that could use LOC RRs to generate a map of hosts and + routers being managed. + +There is the UK based [https://find.me.uk](https://find.me.uk/) whereby you can do: + +```sh +dig loc .find.me.uk +``` + + +There are some behaviours that you should be aware of, however: + +> If omitted, minutes and seconds default to zero, size defaults to 1m, + horizontal precision defaults to 10000m, and vertical precision + defaults to 10m. These defaults are chosen to represent typical + ZIP/postal code area sizes, since it is often easy to find + approximate geographical location by ZIP/postal code. + + +Alas, the world does not revolve around US ZIP codes, but here we are. Internally, +the LOC record type will supply defaults where values were absent on DNS import. +One must supply the `LOC()` js helper all parameters. If that seems like too +much work, see also helper functions: + +* [`LOC_BUILDER_DD()`](../record/LOC_BUILDER_DD.md) - build a `LOC` by supplying only **d**ecimal **d**egrees. +* [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E +* [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E +* [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() + + +## Format ## + +The coordinate format for `LOC()` is: + +`degrees,minutes,seconds,[NnSs],deg,min,sec,[EeWw],altitude,size,horizontal_precision,vertical_precision` + + +## Examples ## + +{% code title="dnsconfig.js" %} +```javascript +D("foo.com","none" + // LOC "subdomain", d1, m1, s1, "[NnSs]", d2, m2, s2, "[EeWw]", alt, siz, hp, vp) + //42 21 54 N 71 06 18 W -24m 30m + , LOC("@", 42, 21, 54, "N", 71, 6, 18, "W", -24, 30, 0, 0) + //42 21 43.952 N 71 5 6.344 W -24m 1m 200m 10m + , LOC("a", 42, 21, 43.952, "N", 71, 5, 6.344, "W", -24, 1, 200, 10) + //52 14 05 N 00 08 50 E 10m + , LOC("b", 52, 14, 5, "N", 0, 8, 50, "E", 10, 0, 0, 0) + //32 7 19 S 116 2 25 E 10m + , LOC("c", 32, 7, 19, "S",116, 2, 25, "E", 10, 0, 0, 0) + //42 21 28.764 N 71 00 51.617 W -44m 2000m + , LOC("d", 42, 21, 28.764, "N", 71, 0, 51.617, "W", -44, 2000, 0, 0) +); + +``` +{% endcode %} diff --git a/documentation/functions/record/LOC_BUILDER_DD.md b/documentation/functions/record/LOC_BUILDER_DD.md new file mode 100644 index 000000000..7f810806f --- /dev/null +++ b/documentation/functions/record/LOC_BUILDER_DD.md @@ -0,0 +1,68 @@ +--- +name: LOC_BUILDER_DD +parameters: + - subdomain + - decimal_degrees_x + - decimal_degrees_y + - altitude + - ttl +parameter_types: + subdomain: string + decimal_degrees_x: float32 + decimal_degrees_y: float32 + altitude: float32 + ttl: int +--- + +`LOC_BUILDER_DD({})` actually takes an object with the mentioned properties. + +A helper to build [`LOC`](../domain/LOC.md) records. Supply four parameters instead of 12. + +Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + + +The cartesian coordinates are decimal degrees, like you typically find in e.g. Google Maps. + +Examples. + +Big Ben: +`51.50084265331501, -0.12462541415599787` + +The White House: +`38.89775977858357, -77.03655125982903` + + +{% code title="dnsconfig.js" %} +```javascript +D("example.com","none" + , LOC_BUILDER_DD({ + label: "big-ben", + x: 51.50084265331501, + y: -0.12462541415599787, + alt: 6, + }) + , LOC_BUILDER_DD({ + label: "white-house", + x: 38.89775977858357, + y: -77.03655125982903, + alt: 19, + }) + , LOC_BUILDER_DD({ + label: "white-house-ttl", + x: 38.89775977858357, + y: -77.03655125982903, + alt: 19, + ttl: "5m", + }) +); + +``` +{% endcode %} + + +Part of the series: + * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() diff --git a/documentation/functions/record/LOC_BUILDER_DMM_STR.md b/documentation/functions/record/LOC_BUILDER_DMM_STR.md new file mode 100644 index 000000000..74350e1bb --- /dev/null +++ b/documentation/functions/record/LOC_BUILDER_DMM_STR.md @@ -0,0 +1,49 @@ +--- +name: LOC_BUILDER_DMM +parameters: + - subdomain + - input_string + - altitude + - ttl +parameter_types: + subdomain: string + input_string: string + altitude: float32 + ttl: int +--- + +`LOC_BUILDER_DMM({})` actually takes an object with the mentioned properties. + +A helper to build [`LOC`](../domain/LOC.md) records. Supply three parameters instead of 12. + +Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + + +Accepts a string with decimal minutes (DMM) coordinates in the form: 25.24°S 153.15°E + +Note that the following are acceptable forms (symbols differ): +* `25.24°S 153.15°E` +* `25.24 S 153.15 E` +* `25.24° S 153.15° E` +* `25.24S 153.15E` + +{% code title="dnsconfig.js" %} +```javascript +D("example.com","none" + LOC_BUILDER_STR({ + label: "tasmania", + str: '42°S 147°E', + alt: 3, + }) +); + +``` +{% endcode %} + + +Part of the series: + * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() diff --git a/documentation/functions/record/LOC_BUILDER_DMS_STR.md b/documentation/functions/record/LOC_BUILDER_DMS_STR.md new file mode 100644 index 000000000..fb37c32e3 --- /dev/null +++ b/documentation/functions/record/LOC_BUILDER_DMS_STR.md @@ -0,0 +1,50 @@ +--- +name: LOC_BUILDER_DMS_STR +parameters: + - subdomain + - input_string + - altitude + - ttl +parameter_types: + subdomain: string + input_string: string + altitude: float32 + ttl: int +--- + +`LOC_BUILDER_DMS_STR({})` actually takes an object with the mentioned properties. + +A helper to build [`LOC`](../domain/LOC.md) records. Supply three parameters instead of 12. + +Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + + +Accepts a string with degrees, minutes, and seconds (DMS) coordinates in the form: 41°24'12.2"N 2°10'26.5"E + +Note that the following are acceptable forms (symbols differ): +* `33°51′31″S 151°12′51″E` +* `33°51'31"S 151°12'51"E` +* `33d51m31sS 151d12m51sE` +* `33d51m31s S 151d12m51s E` + +{% code title="dnsconfig.js" %} +```javascript +D("example.com","none" + LOC_BUILDER_DMS_STR({ + label: "sydney-opera-house", + str: '33°51′31″S 151°12′51″E', + alt: 4, + ttl: "5m", + }) +); + +``` +{% endcode %} + + +Part of the series: + * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() diff --git a/documentation/functions/record/LOC_BUILDER_STRING.md b/documentation/functions/record/LOC_BUILDER_STRING.md new file mode 100644 index 000000000..597d50403 --- /dev/null +++ b/documentation/functions/record/LOC_BUILDER_STRING.md @@ -0,0 +1,57 @@ +--- +name: LOC_BUILDER_STR +parameters: + - subdomain + - input_string + - altitude + - ttl +parameter_types: + subdomain: string + input_string: string + altitude: float32 + ttl: int +--- + +`LOC_BUILDER_STR({})` actually takes an object with the mentioned properties. + +A helper to build [`LOC`](../domain/LOC.md) records. Supply three parameters instead of 12. + +Internally assumes some defaults for [`LOC`](../domain/LOC.md) records. + + +Accepts a string and tries all `LOC_BUILDER_DM*_STR({})` methods: +* [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E +* [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + + + +{% code title="dnsconfig.js" %} +```javascript +D("example.com","none" + , LOC_BUILDER_STR({ + label: "old-faithful", + str: '44.46046°N 110.82815°W', + alt: 2240, + }) + , LOC_BUILDER_STR({ + label: "ribblehead-viaduct", + str: '54.210436°N 2.370231°W', + alt: 300, + }) + , LOC_BUILDER_STR({ + label: "guinness-brewery", + str: '53°20′40″N 6°17′20″W', + alt: 300, + }) +); + +``` +{% endcode %} + + +Part of the series: + * [`LOC()`](LOC.md) - build a `LOC` by supplying all 12 parameters + * [`LOC_BUILDER_DD({})`](../record/LOC_BUILDER_DD.md) - accepts cartesian x, y + * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E + * [`LOC_BUILDER_DMM_STR({})`](LOC_BUILDER_DMM_STR.md) - accepts DMM 25.24°S 153.15°E + * [`LOC_BUILDER_STR({})`](LOC_BUILDER_STR.md) - tries LOC_BUILDER_DM*STR() diff --git a/documentation/providers.md b/documentation/providers.md index 60d55d2aa..de5995649 100644 --- a/documentation/providers.md +++ b/documentation/providers.md @@ -12,53 +12,53 @@ a provider that supports it, we'd love your contribution to ensure it works corr If a feature is definitively not supported for whatever reason, we would also like a PR to clarify why it is not supported, and fill in this entire matrix. -| Provider name | Official Support | DNS Provider | Registrar | ALIAS | AUTODNSSEC | CAA | PTR | NAPTR | SOA | SRV | SSHFP | TLSA | DS | dual host | create-domains | NO_PURGE | get-zones | -| ------------- | ---------------- | ------------ | --------- | ----- | ---------- | --- | --- | ----- | --- | --- | ----- | ---- | -- | --------- | -------------- | -------- | --------- | -| `AKAMAIEDGEDNS` | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | -| `AUTODNS` | ❌ | ✅ | ❌ | ✅ | ❔ | ❌ | ❌ | ❔ | ❔ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | -| `AXFRDDNS` | ❌ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❌ | ❌ | ❌ | ❌ | -| `AZURE_DNS` | ✅ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ❌ | ❔ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | -| `BIND` | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | -| `CLOUDFLAREAPI` | ✅ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ❌ | ✅ | ✅ | ✅ | -| `CLOUDNS` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | -| `CSCGLOBAL` | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ✅ | -| `DESEC` | ❌ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | -| `DIGITALOCEAN` | ❌ | ✅ | ❌ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ | -| `DNSIMPLE` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | -| `DNSMADEEASY` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | -| `DNSOVERHTTPS` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | -| `DOMAINNAMESHOP` | ❌ | ✅ | ❌ | ❔ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | -| `EASYNAME` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | -| `EXOSCALE` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ❔ | ❌ | ❔ | ❌ | ❌ | ✅ | ❔ | -| `GANDI_V5` | ❌ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❌ | ❔ | ❌ | ❌ | ✅ | -| `GCLOUD` | ✅ | ✅ | ❌ | ❔ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | -| `GCORE` | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | -| `HEDNS` | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | -| `HETZNER` | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ❔ | ❔ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | -| `HEXONET` | ❌ | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | -| `HOSTINGDE` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `INTERNETBS` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | -| `INWX` | ❌ | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | -| `LINODE` | ❌ | ✅ | ❌ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ✅ | -| `LOOPIA` | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | -| `LUADNS` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | -| `MSDNS` | ✅ | ✅ | ❌ | ❌ | ❔ | ❌ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ✅ | -| `NAMECHEAP` | ❌ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ❔ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❌ | ❌ | ✅ | -| `NAMEDOTCOM` | ❌ | ✅ | ✅ | ✅ | ❔ | ❔ | ❌ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ❌ | ✅ | ✅ | -| `NETCUP` | ❌ | ✅ | ❌ | ❔ | ❔ | ✅ | ❌ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❌ | -| `NETLIFY` | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | -| `NS1` | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `OPENSRS` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | -| `ORACLE` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | -| `OVH` | ❌ | ✅ | ✅ | ❌ | ❔ | ✅ | ❌ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ✅ | ✅ | -| `PACKETFRAME` | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❔ | -| `PORKBUN` | ❌ | ✅ | ❌ | ✅ | ❌ | ❔ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | -| `POWERDNS` | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `ROUTE53` | ✅ | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ | ✅ | -| `RWTH` | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ❌ | ❔ | ❌ | ❌ | ✅ | ✅ | -| `SOFTLAYER` | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | -| `TRANSIP` | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❌ | ❔ | ❌ | ✅ | ✅ | -| `VULTR` | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ❔ | ❔ | ✅ | ✅ | ❌ | ❔ | ❔ | ✅ | ✅ | ✅ | +| Provider name | Official Support | DNS Provider | Registrar | ALIAS | AUTODNSSEC | CAA | LOC | PTR | NAPTR | SOA | SRV | SSHFP | TLSA | DS | dual host | create-domains | NO_PURGE | get-zones | +| ------------- | ---------------- | ------------ | --------- | ----- | ---------- | --- | --- | --- | ----- | --- | --- | ----- | ---- | -- | --------- | -------------- | -------- | --------- | +| `AKAMAIEDGEDNS` | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | +| `AUTODNS` | ❌ | ✅ | ❌ | ✅ | ❔ | ❌ | ❔ | ❌ | ❔ | ❔ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `AXFRDDNS` | ❌ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❌ | ❌ | ❌ | ❌ | +| `AZURE_DNS` | ✅ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ✅ | ❌ | ❔ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | +| `BIND` | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | +| `CLOUDFLAREAPI` | ✅ | ✅ | ❌ | ✅ | ❔ | ✅ | ❌ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ❌ | ✅ | ✅ | ✅ | +| `CLOUDNS` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | +| `CSCGLOBAL` | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ✅ | +| `DESEC` | ❌ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | +| `DIGITALOCEAN` | ❌ | ✅ | ❌ | ❔ | ❔ | ✅ | ❌ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ | +| `DNSIMPLE` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❔ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `DNSMADEEASY` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ❌ | ✅ | ❔ | ❔ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| `DNSOVERHTTPS` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | +| `DOMAINNAMESHOP` | ❌ | ✅ | ❌ | ❔ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | +| `EASYNAME` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | +| `EXOSCALE` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ❌ | ✅ | ❔ | ❔ | ✅ | ❔ | ❌ | ❔ | ❌ | ❌ | ✅ | ❔ | +| `GANDI_V5` | ❌ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❌ | ❔ | ❌ | ❌ | ✅ | +| `GCLOUD` | ✅ | ✅ | ❌ | ❔ | ❔ | ✅ | ❌ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | +| `GCORE` | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❔ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| `HEDNS` | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| `HETZNER` | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ❌ | ❔ | ❔ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | +| `HEXONET` | ❌ | ✅ | ✅ | ❌ | ❔ | ✅ | ❔ | ✅ | ❔ | ❔ | ✅ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | +| `HOSTINGDE` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `INTERNETBS` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | +| `INWX` | ❌ | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | +| `LINODE` | ❌ | ✅ | ❌ | ❔ | ❔ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ✅ | +| `LOOPIA` | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | +| `LUADNS` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ❌ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | +| `MSDNS` | ✅ | ✅ | ❌ | ❌ | ❔ | ❌ | ❌ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ✅ | +| `NAMECHEAP` | ❌ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ❌ | ❔ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❌ | ❌ | ✅ | +| `NAMEDOTCOM` | ❌ | ✅ | ✅ | ✅ | ❔ | ❔ | ❌ | ❌ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ❌ | ✅ | ✅ | +| `NETCUP` | ❌ | ✅ | ❌ | ❔ | ❔ | ✅ | ❌ | ❌ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❌ | +| `NETLIFY` | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❔ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `NS1` | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `OPENSRS` | ❌ | ❌ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | +| `ORACLE` | ❌ | ✅ | ❌ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | +| `OVH` | ❌ | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ❌ | ❔ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ✅ | ✅ | +| `PACKETFRAME` | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❔ | +| `PORKBUN` | ❌ | ✅ | ❌ | ✅ | ❌ | ❔ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `POWERDNS` | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `ROUTE53` | ✅ | ✅ | ✅ | ❌ | ❔ | ✅ | ❌ | ✅ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ | ✅ | +| `RWTH` | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ✅ | ❌ | ❔ | ✅ | ✅ | ❌ | ❔ | ❌ | ❌ | ✅ | ✅ | +| `SOFTLAYER` | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❌ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ | ❔ | +| `TRANSIP` | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❌ | ❔ | ❌ | ✅ | ✅ | +| `VULTR` | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❌ | ❌ | ❔ | ❔ | ✅ | ✅ | ❌ | ❔ | ❔ | ✅ | ✅ | ✅ | ### Providers with "official support" diff --git a/integrationTest/integration_test.go b/integrationTest/integration_test.go index a201fa226..7a7f29e21 100644 --- a/integrationTest/integration_test.go +++ b/integrationTest/integration_test.go @@ -437,6 +437,13 @@ func cfWorkerRoute(pattern, target string) *models.RecordConfig { return r } +func loc(name string, d1 uint8, m1 uint8, s1 float32, ns string, + d2 uint8, m2 uint8, s2 float32, ew string, al int32, sz float32, hp float32, vp float32) *models.RecordConfig { + r := makeRec(name, "", "LOC") + r.SetLOCParams(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp) + return r +} + func ns(name, target string) *models.RecordConfig { return makeRec(name, target, "NS") } @@ -1438,6 +1445,25 @@ func makeTests(t *testing.T) []*TestGroup { // CNAME at the apex. If we extend IGNORE_TARGET to support other // types of records, we should add a test at the apex. + // LOCation records. // No.47 + testgroup("LOC", + //42 21 54 N 71 06 18 W -24m 30m + tc("Single LOC record", loc("@", 42, 21, 54, "N", 71, 6, 18, "W", -24, 30, 0, 0)), + //42 21 54 N 71 06 18 W -24m 30m + tc("Update single LOC record", loc("@", 42, 21, 54, "N", 71, 6, 18, "W", -24, 30, 10, 0)), + tc("Multiple LOC records-create a-d modify apex", //create a-d, modify @ + //42 21 54 N 71 06 18 W -24m 30m + loc("@", 42, 21, 54, "N", 71, 6, 18, "W", -24, 30, 0, 0), + //42 21 43.952 N 71 5 6.344 W -24m 1m 200m + loc("a", 42, 21, 43.952, "N", 71, 5, 6.344, "W", -24, 1, 200, 10), + //52 14 05 N 00 08 50 E 10m + loc("b", 52, 14, 5, "N", 0, 8, 50, "E", 10, 0, 0, 0), + //32 7 19 S 116 2 25 E 10m + loc("c", 32, 7, 19, "S", 116, 2, 25, "E", 10, 0, 0, 0), + //42 21 28.764 N 71 00 51.617 W -44m 2000m + loc("d", 42, 21, 28.764, "N", 71, 0, 51.617, "W", -44, 2000, 0, 0), + ), + ), } return tests diff --git a/models/dnsrr.go b/models/dnsrr.go index 7f7d2ffd4..6fbb5e330 100644 --- a/models/dnsrr.go +++ b/models/dnsrr.go @@ -76,6 +76,8 @@ func RRtoRC(rr dns.RR, origin string) (RecordConfig, error) { err = rc.SetTarget(v.Target) case *dns.DS: err = rc.SetTargetDS(v.KeyTag, v.Algorithm, v.DigestType, v.Digest) + case *dns.LOC: + err = rc.SetTargetLOC(v.Version, v.Latitude, v.Longitude, v.Altitude, v.Size, v.HorizPre, v.VertPre) case *dns.MX: err = rc.SetTargetMX(v.Preference, v.Mx) case *dns.NS: diff --git a/models/record.go b/models/record.go index 3ab0ce59c..11fa2ed11 100644 --- a/models/record.go +++ b/models/record.go @@ -22,6 +22,7 @@ import ( // ANAME // Technically not an official rtype yet. // CAA // CNAME +// LOC // MX // NAPTR // NS @@ -103,6 +104,13 @@ type RecordConfig struct { DsAlgorithm uint8 `json:"dsalgorithm,omitempty"` DsDigestType uint8 `json:"dsdigesttype,omitempty"` DsDigest string `json:"dsdigest,omitempty"` + LocVersion uint8 `json:"locversion,omitempty"` + LocSize uint8 `json:"locsize,omitempty"` + LocHorizPre uint8 `json:"lochorizpre,omitempty"` + LocVertPre uint8 `json:"locvertpre,omitempty"` + LocLatitude uint32 `json:"loclatitude,omitempty"` + LocLongitude uint32 `json:"loclongitude,omitempty"` + LocAltitude uint32 `json:"localtitude,omitempty"` NaptrOrder uint16 `json:"naptrorder,omitempty"` NaptrPreference uint16 `json:"naptrpreference,omitempty"` NaptrFlags string `json:"naptrflags,omitempty"` @@ -164,6 +172,13 @@ func (rc *RecordConfig) UnmarshalJSON(b []byte) error { DsAlgorithm uint8 `json:"dsalgorithm,omitempty"` DsDigestType uint8 `json:"dsdigesttype,omitempty"` DsDigest string `json:"dsdigest,omitempty"` + LocVersion uint8 `json:"locversion,omitempty"` + LocSize uint8 `json:"locsize,omitempty"` + LocHorizPre uint8 `json:"lochorizpre,omitempty"` + LocVertPre uint8 `json:"locvertpre,omitempty"` + LocLatitude int `json:"loclatitude,omitempty"` + LocLongitude int `json:"loclongitude,omitempty"` + LocAltitude uint32 `json:"localtitude,omitempty"` NaptrOrder uint16 `json:"naptrorder,omitempty"` NaptrPreference uint16 `json:"naptrpreference,omitempty"` NaptrFlags string `json:"naptrflags,omitempty"` @@ -376,6 +391,17 @@ func (rc *RecordConfig) ToRR() dns.RR { rr.(*dns.DS).DigestType = rc.DsDigestType rr.(*dns.DS).Digest = rc.DsDigest rr.(*dns.DS).KeyTag = rc.DsKeyTag + case dns.TypeLOC: + //this is for records from .js files and read from API + // fmt.Printf("ToRR long: %d, lat:%d, sz: %d, hz:%d, vt:%d\n", rc.LocLongitude, rc.LocLatitude, rc.LocSize, rc.LocHorizPre, rc.LocVertPre) + // fmt.Printf("ToRR rc: %+v\n", *rc) + rr.(*dns.LOC).Version = rc.LocVersion + rr.(*dns.LOC).Longitude = rc.LocLongitude + rr.(*dns.LOC).Latitude = rc.LocLatitude + rr.(*dns.LOC).Altitude = rc.LocAltitude + rr.(*dns.LOC).Size = rc.LocSize + rr.(*dns.LOC).HorizPre = rc.LocHorizPre + rr.(*dns.LOC).VertPre = rc.LocVertPre case dns.TypePTR: rr.(*dns.PTR).Ptr = rc.GetTargetField() case dns.TypeNAPTR: @@ -542,6 +568,8 @@ func downcase(recs []*RecordConfig) { case "ANAME", "CNAME", "DS", "MX", "NS", "PTR", "NAPTR", "SRV", "TLSA", "AKAMAICDN": // These record types have a target that is case insensitive, so we downcase it. r.target = strings.ToLower(r.target) + case "LOC": + // Do nothing to affect case of letters. case "A", "AAAA", "ALIAS", "CAA", "IMPORT_TRANSFORM", "TXT", "SSHFP", "CF_REDIRECT", "CF_TEMP_REDIRECT", "CF_WORKER_ROUTE": // These record types have a target that is case sensitive, or is an IP address. We leave them alone. // Do nothing. diff --git a/models/t_loc.go b/models/t_loc.go new file mode 100644 index 000000000..f4c641f58 --- /dev/null +++ b/models/t_loc.go @@ -0,0 +1,187 @@ +package models + +import ( + "fmt" + "strconv" + "strings" + + "github.com/miekg/dns" +) + +// SetTargetLOC sets the LOC fields from the rr.LOC type properties. +func (rc *RecordConfig) SetTargetLOC(ver uint8, lat uint32, lon uint32, alt uint32, siz uint8, hzp uint8, vtp uint8) error { + rc.LocVersion = ver + rc.LocLatitude = lat + rc.LocLongitude = lon + rc.LocAltitude = alt + rc.LocSize = siz + rc.LocHorizPre = hzp + rc.LocVertPre = vtp + + if rc.Type == "" { + rc.Type = "LOC" + } + if rc.Type != "LOC" { + panic("assertion failed: SetTargetLOC called when .Type is not LOC") + } + return nil +} + +// SetLOCParams is an intermediate function which passes the 12 input parameters +// for further processing to the LOC native 7 input binary format: +// LocVersion (0), LocLatitude, LocLongitude, LocAltitude, LocSize, LocVertPre, LocHorizPre +func (rc *RecordConfig) SetLOCParams(d1 uint8, m1 uint8, s1 float32, ns string, + d2 uint8, m2 uint8, s2 float32, ew string, al int32, sz float32, hp float32, vp float32) error { + + err := rc.calculateLOCFields(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp) + + return err +} + +// SetTargetLOCString is like SetTargetLOC but accepts one big string and origin +// Normally this is used when we receive a record string from provider records +// because e.g. the provider API passed rc.PopulateFromString() +func (rc *RecordConfig) SetTargetLOCString(origin string, contents string) error { + // This is where text from provider records ingresses into the target field. + // Fill the other fields derived from the TEXT here. LOC is special, and + // needs more math. + // We have to re-invent the wheel because the miekg dns library gives no + // access to the objects properties, and internally the object is represented + // by the dns.LOC format 💩 + + // Build a string with which to init the rr.LOC object: + str := fmt.Sprintf("%s. LOC %s\n", origin, contents) + loc, err := dns.NewRR(str) + if err != nil { + return fmt.Errorf("can't parse LOC data: %w", err) + } + // We 'normalize' the record thru rr.LOC, to get defaults for absent properties. + + loctext := loc.String() + loctext = strings.TrimSpace(strings.Split(loctext, "LOC")[1]) + + err = rc.extractLOCFieldsFromStringInput(loctext) + if err != nil { + return fmt.Errorf("can't extractLOCFieldsFromStringInput from LOC data: %w", err) + } + rc.target = loctext + if rc.Type == "" { + rc.Type = "LOC" + } + if rc.Type != "LOC" { + panic("assertion failed: SetTargetLOC called when .Type is not LOC") + } + return nil +} + +// extractLOCFieldsFromStringInput is a helper to split an input string to +// the 12 variable inputs of integers and strings. +func (rc *RecordConfig) extractLOCFieldsFromStringInput(input string) error { + var d1, m1, d2, m2 uint8 + var al int32 + var s1, s2 float32 + var ns, ew string + var sz, hp, vp float32 + + var err error + _, err = fmt.Sscanf(input+"~", "%d %d %f %s %d %d %f %s %dm %fm %fm %fm~", + &d1, &m1, &s1, &ns, &d2, &m2, &s2, &ew, &al, &sz, &hp, &vp) + if err != nil { + return fmt.Errorf("extractLOCFieldsFromStringInput: can't unpack LOC tex input data: %w", err) + } + // fmt.Printf("\ngot: %d %d %g %s %d %d %g %s %dm %0.2fm %0.2fm %0.2fm \n", d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp) + + rc.calculateLOCFields(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp) + + return nil +} + +// calculateLOCFields converts from 12 user inputs to the LOC 7 binary fields +func (rc *RecordConfig) calculateLOCFields(d1 uint8, m1 uint8, s1 float32, ns string, + d2 uint8, m2 uint8, s2 float32, ew string, al int32, sz float32, hp float32, vp float32) error { + // Crazy hairy shit happens here. + // We already got the useful "string" version earlier. ¯\_(ツ)_/¯ code golf... + const LOCEquator uint64 = 0x80000000 // 1 << 31 // RFC 1876, Section 2. + const LOCPrimeMeridian uint64 = 0x80000000 // 1 << 31 // RFC 1876, Section 2. + const LOCHours uint32 = 60 * 1000 + const LOCDegrees = 60 * LOCHours + const LOCAltitudeBase int32 = 100000 + + lat := uint64((uint32(d1) * LOCDegrees) + (uint32(m1) * LOCHours) + uint32(s1*1000)) + lon := uint64((uint32(d2) * LOCDegrees) + (uint32(m2) * LOCHours) + uint32(s2*1000)) + if strings.ToUpper(ns) == "N" { + rc.LocLatitude = uint32(LOCEquator + lat) + } else { // "S" + rc.LocLatitude = uint32(LOCEquator - lat) + } + if strings.ToUpper(ew) == "E" { + rc.LocLongitude = uint32(LOCPrimeMeridian + lon) + } else { // "W" + rc.LocLongitude = uint32(LOCPrimeMeridian - lon) + } + // Altitude + rc.LocAltitude = uint32(al+LOCAltitudeBase) * 100 + var err error + // Size + rc.LocSize, err = getENotationInt(sz) + if err != nil { + return err + } + // Horizontal Precision + rc.LocHorizPre, err = getENotationInt(hp) + if err != nil { + return err + } + // Vertical Precision + rc.LocVertPre, err = getENotationInt(vp) + if err != nil { + return err + } + // if hp != 0 { + // } else { + // rc.LocHorizPre = 22 // 1e6 10,000m default + // } + // if vp != 0 { + // } else { + // rc.LocVertPre = 19 // 1e3 10m default + // } + + return nil +} + +// getENotationInt produces a mantissa_exponent 4bits:4bits into a uint8 +func getENotationInt(x float32) (uint8, error) { + /* + 9000000000cm = 9e9 == 153 (9^4 + 9) or 9<<4 + 9 + 800000000cm = 8e8 == 136 (8^4 + 8) or 8<<4 + 8 + 70000000cm = 7e7 == 119 (7^4 + 7) or 7<<4 + 7 + 6000000cm = 6e6 == 102 (6^4 + 6) or 6<<4 + 6 + 1000000cm = 1e6 == 22 (1^4 + 6) or 1<<4 + 6 + 500000cm = 5e5 == 85 (5^4 + 5) or 5<<4 + 5 + 40000cm = 4e4 == 68 (4^4 + 4) or 4<<4 + 4 + 3000cm = 3e3 == 51 (3^4 + 3) or 3<<4 + 3 + 1000cm = 1e3 == 19 (1^4 + 3) or 1<<4 + 1 + 200cm = 2e2 == 34 (2^4 + 2) or 2<<4 + 2 + 100cm = 1e2 == 18 (1^4 + 2) or 1<<4 + 2 + 10cm = 1e1 == 17 (1^4 + 1) or 1<<4 + 1 + 1cm = 1e0 == 16 (1^4 + 0) or 0<<4 + 0 + 0cm = 0e0 == 0 + */ + // get int from cm value: + num := strconv.Itoa(int(x * 100)) + // fmt.Printf("num: %s\n", num) + // split string on zeroes to count zeroes: + arr := strings.Split(num, "0") + // fmt.Printf("arr: %s\n", arr) + // get the leading digit: + prefix, err := strconv.Atoi(arr[0]) + if err != nil { + return 0, fmt.Errorf("can't unpack LOC base/mantissa: %w", err) + } + // fmt.Printf("prefix: %d\n", prefix) + // fmt.Printf("lenArr-1: %d\n", len(arr)-1) + // construct our x^e uint8 + value := uint8((prefix << 4) | (len(arr) - 1)) + // fmt.Printf("m_e: %d\n", value) + return value, err +} diff --git a/models/t_parse.go b/models/t_parse.go index 73ea37d4c..586b6fe67 100644 --- a/models/t_parse.go +++ b/models/t_parse.go @@ -55,6 +55,8 @@ func (rc *RecordConfig) PopulateFromString(rtype, contents, origin string) error return rc.SetTargetCAAString(contents) case "DS": return rc.SetTargetDSString(contents) + case "LOC": + return rc.SetTargetLOCString(origin, contents) case "MX": return rc.SetTargetMXString(contents) case "NAPTR": diff --git a/pkg/js/helpers.js b/pkg/js/helpers.js index d937dfe5c..c18e07c08 100644 --- a/pkg/js/helpers.js +++ b/pkg/js/helpers.js @@ -532,6 +532,216 @@ var TXT = recordBuilder('TXT', { }, }); +// Parses coordinates of the form 41°24'12.2"N 2°10'26.5"E +function parseDMSCoordinatesString(inputString) { + var lat = inputString.match(/(-?\d+).(\d+).([\d\.]+).?\ ?([NS])/); + var lon = inputString.match(/(-?\d+).(\d+).([\d\.]+).?\ ?([EW])/); + + if (!lat || !lon) { + return null; + } + + return { + lati: { + dg: parseInt(lat[1]), + mn: parseInt(lat[2]), + sc: parseFloat(lat[3]), + hemi: lat[4], + }, + long: { + dg: parseInt(lon[1]), + mn: parseInt(lon[2]), + sc: parseFloat(lon[3]), + hemi: lon[4], + }, + }; +} + +// // Parses coordinates of the form 25.24°S 153.15°E +function parseDMMCoordinatesString(inputString) { + var lat = inputString.match(/(-?\d+(\.\d+)?)°?\s*([NS])/i); + var lon = inputString.match(/(-?\d+(\.\d+)?)°?\s*([EW])/i); + + if (!lat || !lon) { + return null; + } + + var latDeg = Math.floor(parseFloat(lat[1])); + var latMin = Math.floor((parseFloat(lat[1]) - latDeg) * 60); + var latSec = Math.round(((parseFloat(lat[1]) - latDeg) * 60 - latMin) * 60); + var lonDeg = Math.floor(parseFloat(lon[1])); + var lonMin = Math.floor((parseFloat(lon[1]) - lonDeg) * 60); + var lonSec = Math.round(((parseFloat(lon[1]) - lonDeg) * 60 - lonMin) * 60); + + var lati = { + dg: latDeg, + mn: latMin, + sc: latSec, + hemi: lat[3], + }; + var long = { + dg: lonDeg, + mn: lonMin, + sc: lonSec, + hemi: lon[3], + }; + + return { + lati: lati, + long: long, + }; +} + +// builds a uint8 with 4 bit mantissa, 4 bit exponent from a float. +function getENotationInt(x) { + /* + 9000000000cm = 9e9 == 153 (9^4 + 9) or 9<<4 + 9 + 800000000cm = 8e8 == 136 (8^4 + 8) or 8<<4 + 8 + 70000000cm = 7e7 == 119 (7^4 + 7) or 7<<4 + 7 + 6000000cm = 6e6 == 102 (6^4 + 6) or 6<<4 + 6 + 1000000cm = 1e6 == 22 (1^4 + 6) or 1<<4 + 6 + 500000cm = 5e5 == 85 (5^4 + 5) or 5<<4 + 5 + 40000cm = 4e4 == 68 (4^4 + 4) or 4<<4 + 4 + 3000cm = 3e3 == 51 (3^4 + 3) or 3<<4 + 3 + 1000cm = 1e3 == 19 (1^4 + 3) or 1<<4 + 1 + 200cm = 2e2 == 34 (2^4 + 2) or 2<<4 + 2 + 10cm = 1e1 == 17 (1^4 + 1) or 1<<4 + 1 + 1cm = 1e0 == 16 (1^4 + 0) or 0<<4 + 0 + 0cm = 0e0 == 0 + */ + size = x * 100; // get cm value + // get the m^e version of size + array = size.toExponential(0).split('e+').map(Number); + // convert it to 4bit:4bit uint8 + m_e = (array[0] << 4) | array[1]; + return m_e; +} + +// Checks LOC parameters and if all is well, renders them into a 'target' string. +// The LOC record has no target string parameter. It only renders one via String(). +function locStringBuilder(record, args) { + record.name = args.name; + + // technically, we don't need this part to build the text target, but + // it is a good sanity check to compare with later on down the chain + // when you're in the weeds with maths. + // Tests depend on it being present. Changes here must reflect in tests. + nsstring = ''; + ewstring = ''; + precisionbuffer = ''; + ns = args.ns.toUpperCase(); + ew = args.ew.toUpperCase(); + + // Handle N/S coords - can use also s1.toFixed(3) + nsstring = + args.d1.toString() + + ' ' + + args.m1.toString() + + ' ' + + args.s1.toString() + + ' '; + var nsmatches = args.ns.match(/^([NnSs])$/); + if (nsmatches == null) { + throw v + ' is not a valid latitude modifier'; + } else { + nsstring += ns + ' '; + } + // Handle E/W coords - can use also s2.toFixed(3) + ewstring = + args.d2.toString() + + ' ' + + args.m2.toString() + + ' ' + + args.s2.toString() + + ' '; + var nsmatches = args.ew.match(/^([EeWw])$/); + if (nsmatches == null) { + throw v + ' is not a valid longitude modifier'; + } else { + ewstring += ew + ' '; + } + + // handle altitude, size, horizontal precision, vertical precision + precisionbuffer = args.alt.toString() + 'm'; + precisionbuffer += ' ' + args.siz.toString() + 'm'; + precisionbuffer += ' ' + args.hp.toString() + 'm'; + precisionbuffer += ' ' + args.vp.toString() + 'm'; + + record.target = nsstring + ewstring + precisionbuffer; + + return record; +} + +// Renders LOC type internal properties from D˚M'S" parameters. +// Change anything here at your peril. +function locDMSBuilder(record, args) { + LOCEquator = 1 << 31; // RFC 1876, Section 2. + LOCPrimeMeridian = 1 << 31; // RFC 1876, Section 2. + LOCHours = 60 * 1000; + LOCDegrees = 60 * LOCHours; + LOCAltitudeBase = 100000; + + lat = args.d1 * LOCDegrees + args.m1 * LOCHours + args.s1 * 1000; + lon = args.d2 * LOCDegrees + args.m2 * LOCHours + args.s2 * 1000; + if (ns == 'N') record.loclatitude = LOCEquator + lat; + // S + else record.loclatitude = LOCEquator - lat; + if (ew == 'E') record.loclongitude = LOCPrimeMeridian + lon; + // W + else record.loclongitude = LOCPrimeMeridian - lon; + // Altitude + record.localtitude = (args.alt + LOCAltitudeBase) * 100; + // Size + record.locsize = getENotationInt(args.siz); + // Horizontal Precision + m_e = args.hp; + record.lochorizpre = getENotationInt(args.hp); + // if (m_e != 0) { + // } else { + // record.lochorizpre = 22; // 10,000m default + // } + // Vertical Precision + m_e = args.vp; + record.locvertpre = getENotationInt(args.vp); + // if (m_e != 0) { + // } else { + // record.lochorizpre = 19; // 10m default + // } +} + +// LOC(name,d1,m1,s1,ns,d2,m2,s2,ew,alt,siz,hp,vp, recordModifiers...) +var LOC = recordBuilder('LOC', { + args: [ + ['name', _.isString], //i.e. subdomain + ['d1', _.isNumber], // N/S degrees + ['m1', _.isNumber], // N/S minutes + ['s1', _.isNumber], // N/S seconds + ['ns', _.isString], // N/S + ['d2', _.isNumber], // E/W degrees + ['m2', _.isNumber], // E/W minutes + ['s2', _.isNumber], // E/W seconds + ['ew', _.isString], // E/W + ['alt', _.isNumber], // altitude + ['siz', _.isNumber], // size/precision + ['hp', _.isNumber], // horizontal precision + ['vp', _.isNumber], // vertical precision + ], + transform: function (record, args, modifiers) { + record = locStringBuilder(record, args); + record = locDMSBuilder(record, args); + }, +}); + +function ConvertDDToDMS(D, longitude) { + //stackoverflow, baby. do not re-order the rows. + return { + hemi: D < 0 ? (longitude ? 'W' : 'S') : longitude ? 'E' : 'N', + dg: 0 | (D < 0 ? (D = -D) : D), + mn: 0 | (((D += 1e-9) % 1) * 60), + sc: (0 | (((D * 60) % 1) * 60000)) / 1000, + }; +} + // MX(name,priority,target, recordModifiers...) var MX = recordBuilder('MX', { args: [ @@ -987,6 +1197,182 @@ var FRAME = recordBuilder('FRAME'); var NS1_URLFWD = recordBuilder('NS1_URLFWD'); var CLOUDNS_WR = recordBuilder('CLOUDNS_WR'); +// LOC_BUILDER_DD takes an object: +// label: The DNS label for the LOC record. (default: '@') +// x: Decimal X coordinate. +// y: Decimal Y coordinate. +// alt: Altitude in m. You imperial measurement system people are suckers for punishment. +// ttl: The time for TTL, integer or string. (default: not defined, using DefaultTTL) + +function LOC_BUILDER_DD(value) { + if (!value.x && !value.y) { + throw 'LOC_BUILDER_DD requires x and y elements'; + } + + if (!value.label) { + value.label = '@'; + } + + var lati = ConvertDDToDMS(value.x, false); + var long = ConvertDDToDMS(value.y, true); + + dms = { lati: lati, long: long }; + + return LOC_builder_push(value, dms); +} + +// LOC_BUILDER_DMM_STR takes an object: +// label: The DNS label for the LOC record. (default: '@') +// str: Input string of Degrees and decimal minutes (DMM) coordinates in the form: 25.24°S 153.15°E +// alt: Altitude in m. You imperial measurement system people are suckers for punishment. +// ttl: The time for TTL, integer or string. (default: not defined, using DefaultTTL) + +function LOC_BUILDER_DMM_STR(value) { + if (!value.str) { + throw 'LOC_BUILDER_DMM_STR requires a string of the form 25.24°S 153.15°E'; + } + + if (!value.label) { + value.label = '@'; + } + + var dms = parseDMMCoordinatesString(value.str); + + return LOC_builder_push(value, dms); +} + +// LOC_BUILDER_DMS_STR takes an object: +// label: The DNS label for the LOC record. (default: '@') +// str: Input string of degrees, minutes, and seconds (DMS) coordinates in the form: 41°24'12.2"N 2°10'26.5"E +// alt: Altitude in m. You imperial measurement system people are suckers for punishment. +// ttl: The time for TTL, integer or string. (default: not defined, using DefaultTTL) + +function LOC_BUILDER_DMS_STR(value) { + if (!value.str) { + throw 'LOC_BUILDER_DMS_STR requires a string of the form 33°51′31″S 151°12′51″Es (or 33°51\'31"S 151°12\'51"Es)'; + } + + if (!value.label) { + value.label = '@'; + } + + var dms = parseDMSCoordinatesString(value.str); + + return LOC_builder_push(value, dms); +} + +// LOC_BUILDER_STR takes an object: +// label: The DNS label for the LOC record. (default: '@') +// str: Input string of degrees, minutes, and seconds (DMS) coordinates in the form: 41°24'12.2"N 2°10'26.5"E +// alt: Altitude in m. You imperial measurement system people are suckers for punishment. +// ttl: The time for TTL, integer or string. (default: not defined, using DefaultTTL) + +function LOC_BUILDER_STR(value) { + if (!value.str) { + throw 'LOC_BUILDER_STR requires a string'; + } + + if (!value.label) { + value.label = '@'; + } + + var dms = parseDMMCoordinatesString(value.str); + if (!dms) dms = parseDMSCoordinatesString(value.str); + + return LOC_builder_push(value, dms); +} + +function LOC_builder_push(value, dms) { + r = []; // The list of records to return. + p = {}; // The metaparameters to set on the LOC record. + // rawloc = ""; + + // Generate a LOC record with the metaparameters. + if (value.ttl) { + if (value.alt) + r.push( + LOC( + value.label, + dms.lati.dg, + dms.lati.mn, + dms.lati.sc, + dms.lati.hemi, + dms.long.dg, + dms.long.mn, + dms.long.sc, + dms.long.hemi, + value.alt, + 0, + 0, + 0, + p, + TTL(value.ttl) + ) + ); + else + r.push( + LOC( + value.label, + dms.lati.dg, + dms.lati.mn, + dms.lati.sc, + dms.lati.hemi, + dms.long.dg, + dms.long.mn, + dms.long.sc, + dms.long.hemi, + 0, + 0, + 0, + 0, + p, + TTL(value.ttl) + ) + ); + } else { + if (value.alt) + r.push( + LOC( + value.label, + dms.lati.dg, + dms.lati.mn, + dms.lati.sc, + dms.lati.hemi, + dms.long.dg, + dms.long.mn, + dms.long.sc, + dms.long.hemi, + value.alt, + 0, + 0, + 0, + p + ) + ); + else + r.push( + LOC( + value.label, + dms.lati.dg, + dms.lati.mn, + dms.lati.sc, + dms.lati.hemi, + dms.long.dg, + dms.long.mn, + dms.long.sc, + dms.long.hemi, + 0, + 0, + 0, + 0, + p + ) + ); + } + + return r; +} + // SPF_BUILDER takes an object: // parts: The parts of the SPF record (to be joined with ' '). // label: The DNS label for the primary SPF record. (default: '@') diff --git a/pkg/js/parse_tests/045-loc.js b/pkg/js/parse_tests/045-loc.js new file mode 100644 index 000000000..65103dce0 --- /dev/null +++ b/pkg/js/parse_tests/045-loc.js @@ -0,0 +1,79 @@ +D("foo.com","none" + // LOC "subdomain", d1, m1, s1, "[NnSs]", d2, m2, s2, "[EeWw]", alt, siz, hp, vp) + , LOC("@", 42, 21, 54, "N", 71, 6, 18, "W", -24, 30, 0, 0) //42 21 54 N 71 06 18 W -24m 30m + , LOC("a", 42, 21, 43.952, "N", 71, 5, 6.344, "W", -24, 1, 200, 10) //42 21 43.952 N 71 5 6.344 W -24m 1m 200m + , LOC("b", 52, 14, 5, "N", 0, 8, 50, "E", 10, 0, 0, 0) //52 14 05 N 00 08 50 E 10m + , LOC("c", 32, 7, 19, "S",116, 2, 25, "E", 10, 0, 0, 0) //32 7 19 S 116 2 25 E 10m + , LOC("d", 42, 21, 28.764, "N", 71, 0, 51.617, "W", -44, 2000, 0, 0) //42 21 28.764 N 71 00 51.617 W -44m 2000m + + // via the Decimal degrees to LOC builder. + , LOC_BUILDER_DD({ + label: "big-ben", + x: 51.50084265331501, + y: -0.12462541415599787, + alt: 6, + }) + , LOC_BUILDER_DD({ + label: "white-house", + x: 38.89775977858357, + y: -77.03655125982903, + alt: 19, + ttl: "5m", + }) + , LOC_BUILDER_DMS_STR({ + label: "opera-house", + str: '33°51′31″S 151°12′51″E', + alt: 4, + ttl: "5m", + }) + , LOC_BUILDER_DMS_STR({ + label: "opera-house2", + str: '33°51\'31"S 151°12\'51"E', + alt: 4, + ttl: "5m", + }) + , LOC_BUILDER_DMS_STR({ + label: "opera-house3", + str: '33d51m31sS 151d12m51sE', + alt: 4, + ttl: "5m", + }) + , LOC_BUILDER_DMS_STR({ + label: "opera-house4", + str: '33d51m31s S 151d12m51s E', + alt: 4, + ttl: "5m", + }) + , LOC_BUILDER_DMM_STR({ + label: "fraser-island", + str: '25.24°S 153.15°E', + alt: 3, + }) + , LOC_BUILDER_STR({ + label: "tasmania", + str: '42°S 147°E', + alt: 3, + }) + , LOC_BUILDER_STR({ + label: "hawaii", + str: '21.5°N 158.0°W', + alt: 920, + }) + , LOC_BUILDER_STR({ + label: "old-faithful", + str: '44.46046°N 110.82815°W', + alt: 2240, + }) + , LOC_BUILDER_STR({ + label: "ribblehead-viaduct", + str: '54.210436°N 2.370231°W', + alt: 300, + }) + , LOC_BUILDER_STR({ + label: "guinness-brewery", + str: '53°20′40″N 6°17′20″W', + alt: 300, + }) +); + + diff --git a/pkg/js/parse_tests/045-loc.json b/pkg/js/parse_tests/045-loc.json new file mode 100644 index 000000000..68db2435d --- /dev/null +++ b/pkg/js/parse_tests/045-loc.json @@ -0,0 +1,160 @@ + +{ + "registrars": [], + "dns_providers": [], + "domains": [ + { + "name": "foo.com", + "registrar": "none", + "dnsProviders": {}, + "records": [ + { + "type": "LOC", + "name": "@", + "locsize": 51, + "loclatitude": 2299997648, + "loclongitude": 1891505648, + "localtitude": 9997600, + "target": "42 21 54 N 71 6 18 W -24m 30m 0m 0m" + }, + { + "type": "LOC", + "name": "a", + "locsize": 18, + "lochorizpre": 36, + "locvertpre": 19, + "loclatitude": 2299987600, + "loclongitude": 1891577304, + "localtitude": 9997600, + "target": "42 21 43.952 N 71 5 6.344 W -24m 1m 200m 10m" + }, + { + "type": "LOC", + "name": "b", + "loclatitude": 2335528648, + "loclongitude": 2148013648, + "localtitude": 10001000, + "target": "52 14 5 N 0 8 50 E 10m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "c", + "loclatitude": 2031844648, + "loclongitude": 2565228648, + "localtitude": 10001000, + "target": "32 7 19 S 116 2 25 E 10m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "d", + "locsize": 37, + "loclatitude": 2299972412, + "loclongitude": 1891832031, + "localtitude": 9995600, + "target": "42 21 28.764 N 71 0 51.617 W -44m 2000m 0m 0m" + }, + { + "type": "LOC", + "name": "big-ben", + "loclatitude": 2332886681, + "loclongitude": 2147034997, + "localtitude": 10000600, + "target": "51 30 3.033 N 0 7 28.651 W 6m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "white-house", + "ttl": 300, + "loclatitude": 2287515583, + "loclongitude": 1870152064, + "localtitude": 10001900, + "target": "38 53 51.935 N 77 2 11.584 W 19m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "opera-house", + "ttl": 300, + "loclatitude": 2025592648, + "loclongitude": 2691854648, + "localtitude": 10000400, + "target": "33 51 31 S 151 12 51 E 4m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "opera-house2", + "ttl": 300, + "loclatitude": 2025592648, + "loclongitude": 2691854648, + "localtitude": 10000400, + "target": "33 51 31 S 151 12 51 E 4m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "opera-house3", + "ttl": 300, + "loclatitude": 2025592648, + "loclongitude": 2691854648, + "localtitude": 10000400, + "target": "33 51 31 S 151 12 51 E 4m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "opera-house4", + "ttl": 300, + "loclatitude": 2025592648, + "loclongitude": 2691854648, + "localtitude": 10000400, + "target": "33 51 31 S 151 12 51 E 4m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "fraser-island", + "loclatitude": 2056619648, + "loclongitude": 2698823648, + "localtitude": 10000300, + "target": "25 14 24 S 153 9 0 E 3m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "tasmania", + "loclatitude": 1996283648, + "loclongitude": 2676683648, + "localtitude": 10000300, + "target": "42 0 0 S 147 0 0 E 3m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "hawaii", + "loclatitude": 2224883648, + "loclongitude": 1578683648, + "localtitude": 10092000, + "target": "21 30 0 N 158 0 0 W 920m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "old-faithful", + "loclatitude": 2307541648, + "loclongitude": 1748502648, + "localtitude": 10224000, + "target": "44 27 38 N 110 49 41 W 2240m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "ribblehead-viaduct", + "loclatitude": 2342641648, + "loclongitude": 2138950648, + "localtitude": 10030000, + "target": "54 12 38 N 2 22 13 W 300m 0m 0m 0m" + }, + { + "type": "LOC", + "name": "guinness-brewery", + "loclatitude": 2339523648, + "loclongitude": 2124843648, + "localtitude": 10030000, + "target": "53 20 40 N 6 17 20 W 300m 0m 0m 0m" + } + ] + } + ] +} \ No newline at end of file diff --git a/pkg/js/parse_tests/045-loc/foo.com.zone b/pkg/js/parse_tests/045-loc/foo.com.zone new file mode 100644 index 000000000..1e0c3ac97 --- /dev/null +++ b/pkg/js/parse_tests/045-loc/foo.com.zone @@ -0,0 +1,18 @@ +$TTL 300 +@ IN LOC 42 21 54.000 N 71 06 18.000 W -24m 30m 0.00m 0.00m +a IN LOC 42 21 43.952 N 71 05 6.344 W -24m 1m 200m 10m +b IN LOC 52 14 5.000 N 00 08 50.000 E 10m 0.00m 0.00m 0.00m +big-ben IN LOC 51 30 3.033 N 00 07 28.651 W 6m 0.00m 0.00m 0.00m +c IN LOC 32 07 19.000 S 116 02 25.000 E 10m 0.00m 0.00m 0.00m +d IN LOC 42 21 28.764 N 71 00 51.617 W -44m 2000m 0.00m 0.00m +fraser-island IN LOC 25 14 24.000 S 153 09 0.000 E 3m 0.00m 0.00m 0.00m +guinness-brewery IN LOC 53 20 40.000 N 06 17 20.000 W 300m 0.00m 0.00m 0.00m +hawaii IN LOC 21 30 0.000 N 158 00 0.000 W 920m 0.00m 0.00m 0.00m +old-faithful IN LOC 44 27 38.000 N 110 49 41.000 W 2240m 0.00m 0.00m 0.00m +opera-house IN LOC 33 51 31.000 S 151 12 51.000 E 4m 0.00m 0.00m 0.00m +opera-house2 IN LOC 33 51 31.000 S 151 12 51.000 E 4m 0.00m 0.00m 0.00m +opera-house3 IN LOC 33 51 31.000 S 151 12 51.000 E 4m 0.00m 0.00m 0.00m +opera-house4 IN LOC 33 51 31.000 S 151 12 51.000 E 4m 0.00m 0.00m 0.00m +ribblehead-viaduct IN LOC 54 12 38.000 N 02 22 13.000 W 300m 0.00m 0.00m 0.00m +tasmania IN LOC 42 00 0.000 S 147 00 0.000 E 3m 0.00m 0.00m 0.00m +white-house IN LOC 38 53 51.935 N 77 02 11.584 W 19m 0.00m 0.00m 0.00m diff --git a/pkg/normalize/validate.go b/pkg/normalize/validate.go index 4111940fc..5fbf320fa 100644 --- a/pkg/normalize/validate.go +++ b/pkg/normalize/validate.go @@ -61,6 +61,7 @@ func validateRecordTypes(rec *models.RecordConfig, domain string, pTypes []strin "CNAME": true, "DS": true, "IMPORT_TRANSFORM": false, + "LOC": true, "MX": true, "NAPTR": true, "NS": true, @@ -192,6 +193,7 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) { if labelFQDN == targetFQDN { check(fmt.Errorf("CNAME loop (target points at itself)")) } + case "LOC": case "MX": check(checkTarget(target)) case "NAPTR": @@ -277,6 +279,8 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra case "AKAMAICDN", "MX", "NAPTR", "NS", "SOA", "SRV", "TXT", "CAA", "TLSA": // Not imported. continue + case "LOC": + continue default: return fmt.Errorf("import_transform: Unimplemented record type %v (%v)", rec.Type, rec.GetLabel()) @@ -721,6 +725,7 @@ var providerCapabilityChecks = []pairTypeCapability{ capabilityCheck("AUTODNSSEC", providers.CanAutoDNSSEC), capabilityCheck("AZURE_ALIAS", providers.CanUseAzureAlias), capabilityCheck("CAA", providers.CanUseCAA), + capabilityCheck("LOC", providers.CanUseLOC), capabilityCheck("NAPTR", providers.CanUseNAPTR), capabilityCheck("PTR", providers.CanUsePTR), capabilityCheck("R53_ALIAS", providers.CanUseRoute53Alias), diff --git a/providers/akamaiedgedns/akamaiEdgeDnsProvider.go b/providers/akamaiedgedns/akamaiEdgeDnsProvider.go index eb89182c9..8b4535e97 100644 --- a/providers/akamaiedgedns/akamaiEdgeDnsProvider.go +++ b/providers/akamaiedgedns/akamaiEdgeDnsProvider.go @@ -32,6 +32,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), providers.CanUseDSForChildren: providers.Can(), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSOA: providers.Cannot(), diff --git a/providers/axfrddns/axfrddnsProvider.go b/providers/axfrddns/axfrddnsProvider.go index 189239755..866edea04 100644 --- a/providers/axfrddns/axfrddnsProvider.go +++ b/providers/axfrddns/axfrddnsProvider.go @@ -42,6 +42,7 @@ var features = providers.DocumentationNotes{ providers.CanAutoDNSSEC: providers.Can("Just warn when DNSSEC is requested but no RRSIG is found in the AXFR or warn when DNSSEC is not requested but RRSIG are found in the AXFR."), providers.CanGetZones: providers.Cannot(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/azuredns/azureDnsProvider.go b/providers/azuredns/azureDnsProvider.go index 15b69738b..0d80519ed 100644 --- a/providers/azuredns/azureDnsProvider.go +++ b/providers/azuredns/azureDnsProvider.go @@ -60,6 +60,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Cannot("Azure DNS does not provide a generic ALIAS functionality. Use AZURE_ALIAS instead."), providers.CanUseAzureAlias: providers.Can(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/bind/bindProvider.go b/providers/bind/bindProvider.go index d76c7895d..94105133c 100644 --- a/providers/bind/bindProvider.go +++ b/providers/bind/bindProvider.go @@ -37,6 +37,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Can(), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSOA: providers.Can(), diff --git a/providers/capabilities.go b/providers/capabilities.go index b9fd50c0c..3335c8f5a 100644 --- a/providers/capabilities.go +++ b/providers/capabilities.go @@ -40,6 +40,9 @@ const ( // only for children records, not at the root of the zone. CanUseDSForChildren + // CanUseLOC indicates whether service provider handles LOC records + CanUseLOC + // CanUseNAPTR indicates the provider can handle NAPTR records CanUseNAPTR diff --git a/providers/capability_string.go b/providers/capability_string.go index 2bbf626c4..fb35841af 100644 --- a/providers/capability_string.go +++ b/providers/capability_string.go @@ -16,22 +16,23 @@ func _() { _ = x[CanUseCAA-5] _ = x[CanUseDS-6] _ = x[CanUseDSForChildren-7] - _ = x[CanUseNAPTR-8] - _ = x[CanUsePTR-9] - _ = x[CanUseRoute53Alias-10] - _ = x[CanUseSOA-11] - _ = x[CanUseSRV-12] - _ = x[CanUseSSHFP-13] - _ = x[CanUseTLSA-14] - _ = x[CantUseNOPURGE-15] - _ = x[DocCreateDomains-16] - _ = x[DocDualHost-17] - _ = x[DocOfficiallySupported-18] + _ = x[CanUseLOC-8] + _ = x[CanUseNAPTR-9] + _ = x[CanUsePTR-10] + _ = x[CanUseRoute53Alias-11] + _ = x[CanUseSOA-12] + _ = x[CanUseSRV-13] + _ = x[CanUseSSHFP-14] + _ = x[CanUseTLSA-15] + _ = x[CantUseNOPURGE-16] + _ = x[DocCreateDomains-17] + _ = x[DocDualHost-18] + _ = x[DocOfficiallySupported-19] } -const _Capability_name = "CanAutoDNSSECCanGetZonesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDSCanUseDSForChildrenCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseSOACanUseSRVCanUseSSHFPCanUseTLSACantUseNOPURGEDocCreateDomainsDocDualHostDocOfficiallySupported" +const _Capability_name = "CanAutoDNSSECCanGetZonesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDSCanUseDSForChildrenCanUseLOCCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseSOACanUseSRVCanUseSSHFPCanUseTLSACantUseNOPURGEDocCreateDomainsDocDualHostDocOfficiallySupported" -var _Capability_index = [...]uint8{0, 13, 24, 39, 50, 66, 75, 83, 102, 113, 122, 140, 149, 158, 169, 179, 193, 209, 220, 242} +var _Capability_index = [...]uint8{0, 13, 24, 39, 50, 66, 75, 83, 102, 111, 122, 131, 149, 158, 167, 178, 188, 202, 218, 229, 251} func (i Capability) String() string { if i >= Capability(len(_Capability_index)-1) { diff --git a/providers/cloudflare/cloudflareProvider.go b/providers/cloudflare/cloudflareProvider.go index 6ad7276fe..39fade504 100644 --- a/providers/cloudflare/cloudflareProvider.go +++ b/providers/cloudflare/cloudflareProvider.go @@ -42,6 +42,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Can("CF automatically flattens CNAME records into A records dynamically"), providers.CanUseCAA: providers.Can(), providers.CanUseDSForChildren: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/cloudns/cloudnsProvider.go b/providers/cloudns/cloudnsProvider.go index b01a18d5f..c88da87e9 100644 --- a/providers/cloudns/cloudnsProvider.go +++ b/providers/cloudns/cloudnsProvider.go @@ -44,6 +44,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Can(), providers.CanUseCAA: providers.Can(), providers.CanUseDSForChildren: providers.Can(), + providers.CanUseLOC: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/desec/desecProvider.go b/providers/desec/desecProvider.go index d80f68ba8..09e9bceb8 100644 --- a/providers/desec/desecProvider.go +++ b/providers/desec/desecProvider.go @@ -45,6 +45,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Unimplemented("Apex aliasing is supported via new SVCB and HTTPS record types. For details, check the deSEC docs."), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Can(), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/digitalocean/digitaloceanProvider.go b/providers/digitalocean/digitaloceanProvider.go index 0aebb39fe..2c3eb2dee 100644 --- a/providers/digitalocean/digitaloceanProvider.go +++ b/providers/digitalocean/digitaloceanProvider.go @@ -74,6 +74,7 @@ retry: var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseSRV: providers.Can(), providers.DocCreateDomains: providers.Can(), providers.DocOfficiallySupported: providers.Cannot(), diff --git a/providers/dnsimple/dnsimpleProvider.go b/providers/dnsimple/dnsimpleProvider.go index d2c867662..91d18ee65 100644 --- a/providers/dnsimple/dnsimpleProvider.go +++ b/providers/dnsimple/dnsimpleProvider.go @@ -25,6 +25,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), providers.CanUseDSForChildren: providers.Cannot(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/dnsmadeeasy/dnsMadeEasyProvider.go b/providers/dnsmadeeasy/dnsMadeEasyProvider.go index 8965b4488..dcd5ec73b 100644 --- a/providers/dnsmadeeasy/dnsMadeEasyProvider.go +++ b/providers/dnsmadeeasy/dnsMadeEasyProvider.go @@ -19,6 +19,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), providers.CanUseDSForChildren: providers.Cannot(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Cannot(), diff --git a/providers/domainnameshop/domainnameshopProvider.go b/providers/domainnameshop/domainnameshopProvider.go index e9b96d791..e84cc634e 100644 --- a/providers/domainnameshop/domainnameshopProvider.go +++ b/providers/domainnameshop/domainnameshopProvider.go @@ -27,8 +27,9 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Unimplemented(), // providers.CanUseAlias: providers.Unimplemented("Needs custom implementation"), // Can possibly be implemented, needs further research providers.CanUseCAA: providers.Can(), - providers.CanUseDS: providers.Unimplemented(), // Seems to support but needs to be implemented - providers.CanUseDSForChildren: providers.Unimplemented(), // Seems to support but needs to be implemented + providers.CanUseDS: providers.Unimplemented(), // Seems to support but needs to be implemented + providers.CanUseDSForChildren: providers.Unimplemented(), // Seems to support but needs to be implemented + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Cannot("According to Domainnameshop this will probably never be supported"), // Does not seem to support it providers.CanUsePTR: providers.Cannot("According to Domainnameshop this will probably never be supported"), // Seems to support but needs to be implemented providers.CanUseSOA: providers.Cannot(), // Does not seem to support it diff --git a/providers/exoscale/exoscaleProvider.go b/providers/exoscale/exoscaleProvider.go index 708c388f1..a939fae94 100644 --- a/providers/exoscale/exoscaleProvider.go +++ b/providers/exoscale/exoscaleProvider.go @@ -58,6 +58,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Unimplemented(), providers.CanUseAlias: providers.Can(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can("SRV records with empty targets are not supported"), providers.CanUseTLSA: providers.Cannot(), diff --git a/providers/gandiv5/gandi_v5Provider.go b/providers/gandiv5/gandi_v5Provider.go index 457f0b9a8..9f56a1f90 100644 --- a/providers/gandiv5/gandi_v5Provider.go +++ b/providers/gandiv5/gandi_v5Provider.go @@ -51,6 +51,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot("Only supports DS records at the apex"), providers.CanUseDSForChildren: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/gcloud/gcloudProvider.go b/providers/gcloud/gcloudProvider.go index 891094d45..9b1c82eb7 100644 --- a/providers/gcloud/gcloudProvider.go +++ b/providers/gcloud/gcloudProvider.go @@ -25,6 +25,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseCAA: providers.Can(), providers.CanUseDSForChildren: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/gcore/gcoreProvider.go b/providers/gcore/gcoreProvider.go index 1c5ec2031..08343a350 100644 --- a/providers/gcore/gcoreProvider.go +++ b/providers/gcore/gcoreProvider.go @@ -47,6 +47,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Cannot(), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Cannot(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSRV: providers.Can("G-Core doesn't support SRV records with empty targets"), diff --git a/providers/hedns/hednsProvider.go b/providers/hedns/hednsProvider.go index f2429d74b..e606699d5 100644 --- a/providers/hedns/hednsProvider.go +++ b/providers/hedns/hednsProvider.go @@ -49,6 +49,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), providers.CanUseDSForChildren: providers.Cannot(), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSOA: providers.Cannot(), diff --git a/providers/hetzner/hetznerProvider.go b/providers/hetzner/hetznerProvider.go index bc886a3b4..be8c06fd8 100644 --- a/providers/hetzner/hetznerProvider.go +++ b/providers/hetzner/hetznerProvider.go @@ -17,6 +17,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Cannot(), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Cannot(), diff --git a/providers/hostingde/hostingdeProvider.go b/providers/hostingde/hostingdeProvider.go index f39afd478..0665aae49 100644 --- a/providers/hostingde/hostingdeProvider.go +++ b/providers/hostingde/hostingdeProvider.go @@ -23,6 +23,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseSOA: providers.Can(), providers.CanUseDS: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/inwx/inwxProvider.go b/providers/inwx/inwxProvider.go index 8c604b57b..94b49d7b0 100644 --- a/providers/inwx/inwxProvider.go +++ b/providers/inwx/inwxProvider.go @@ -48,6 +48,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Cannot("INWX does not support the ALIAS or ANAME record type."), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Unimplemented("DS records are only supported at the apex and require a different API call that hasn't been implemented yet."), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can("PTR records with empty targets are not supported"), providers.CanUseSRV: providers.Can("SRV records with empty targets are not supported."), diff --git a/providers/linode/linodeProvider.go b/providers/linode/linodeProvider.go index d052fd8e9..98e8537c8 100644 --- a/providers/linode/linodeProvider.go +++ b/providers/linode/linodeProvider.go @@ -88,6 +88,7 @@ func NewLinode(m map[string]string, metadata json.RawMessage) (providers.DNSServ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseCAA: providers.Can("Linode doesn't support changing the CAA flag"), + providers.CanUseLOC: providers.Cannot(), providers.DocDualHost: providers.Cannot(), providers.DocOfficiallySupported: providers.Cannot(), } diff --git a/providers/loopia/loopiaProvider.go b/providers/loopia/loopiaProvider.go index 4f4931fdc..9dc2f70f8 100644 --- a/providers/loopia/loopiaProvider.go +++ b/providers/loopia/loopiaProvider.go @@ -53,6 +53,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot("Only supports DS records at the apex, only for .se and .nu domains; done automatically at back-end."), providers.CanUseDSForChildren: providers.Cannot(), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSOA: providers.Cannot("💩"), diff --git a/providers/luadns/luadnsProvider.go b/providers/luadns/luadnsProvider.go index bb22e33ee..1c6a40048 100644 --- a/providers/luadns/luadnsProvider.go +++ b/providers/luadns/luadnsProvider.go @@ -23,6 +23,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseAlias: providers.Can(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/msdns/msdnsProvider.go b/providers/msdns/msdnsProvider.go index a3b60252b..482716ee9 100644 --- a/providers/msdns/msdnsProvider.go +++ b/providers/msdns/msdnsProvider.go @@ -24,6 +24,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Cannot(), providers.CanUseCAA: providers.Cannot(), providers.CanUseDS: providers.Unimplemented(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/namecheap/namecheapProvider.go b/providers/namecheap/namecheapProvider.go index bc7f56f59..d0d9a28ee 100644 --- a/providers/namecheap/namecheapProvider.go +++ b/providers/namecheap/namecheapProvider.go @@ -30,6 +30,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseAlias: providers.Can(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSRV: providers.Cannot("The namecheap web console allows you to make SRV records, but their api does not let you read or set them"), providers.CanUseTLSA: providers.Cannot(), diff --git a/providers/namedotcom/namedotcomProvider.go b/providers/namedotcom/namedotcomProvider.go index e73ed0c04..fdc6e202c 100644 --- a/providers/namedotcom/namedotcomProvider.go +++ b/providers/namedotcom/namedotcomProvider.go @@ -23,6 +23,7 @@ type namedotcomProvider struct { var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseAlias: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Cannot("PTR records are not supported (See Link)", "https://www.name.com/support/articles/205188508-Reverse-DNS-records"), providers.CanUseSRV: providers.Can("SRV records with empty targets are not supported"), providers.DocCreateDomains: providers.Cannot("New domains require registration"), diff --git a/providers/netcup/netcupProvider.go b/providers/netcup/netcupProvider.go index 1efcef58d..d9b707a9a 100644 --- a/providers/netcup/netcupProvider.go +++ b/providers/netcup/netcupProvider.go @@ -13,6 +13,7 @@ import ( var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Cannot(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSRV: providers.Can(), providers.DocCreateDomains: providers.Cannot(), diff --git a/providers/netlify/netlifyProvider.go b/providers/netlify/netlifyProvider.go index 01f566784..8a93a099d 100644 --- a/providers/netlify/netlifyProvider.go +++ b/providers/netlify/netlifyProvider.go @@ -24,6 +24,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), providers.CanUseDSForChildren: providers.Cannot(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Cannot(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSRV: providers.Can(), diff --git a/providers/ns1/ns1Provider.go b/providers/ns1/ns1Provider.go index 81705320a..a42c5532a 100644 --- a/providers/ns1/ns1Provider.go +++ b/providers/ns1/ns1Provider.go @@ -23,6 +23,7 @@ var docNotes = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Can(), providers.CanUseDSForChildren: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.DocCreateDomains: providers.Can(), diff --git a/providers/oracle/oracleProvider.go b/providers/oracle/oracleProvider.go index a6fdab19d..21251aaf5 100644 --- a/providers/oracle/oracleProvider.go +++ b/providers/oracle/oracleProvider.go @@ -22,6 +22,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Can(), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), // should be supported, but getting 500s in tests + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/ovh/ovhProvider.go b/providers/ovh/ovhProvider.go index da1470a98..1e1eaa182 100644 --- a/providers/ovh/ovhProvider.go +++ b/providers/ovh/ovhProvider.go @@ -22,6 +22,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseAlias: providers.Cannot(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Can(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/porkbun/porkbunProvider.go b/providers/porkbun/porkbunProvider.go index a87402008..0346d77c4 100644 --- a/providers/porkbun/porkbunProvider.go +++ b/providers/porkbun/porkbunProvider.go @@ -50,6 +50,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Unimplemented(), // CAA record for base domain is pinning to a fixed set once configure providers.CanUseDS: providers.Cannot(), providers.CanUseDSForChildren: providers.Cannot(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Cannot(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSOA: providers.Cannot(), diff --git a/providers/powerdns/powerdnsProvider.go b/providers/powerdns/powerdnsProvider.go index 69baca541..825923b75 100644 --- a/providers/powerdns/powerdnsProvider.go +++ b/providers/powerdns/powerdnsProvider.go @@ -15,6 +15,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Can("Needs to be enabled in PowerDNS first", "https://doc.powerdns.com/authoritative/guides/alias.html"), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Can(), + providers.CanUseLOC: providers.Can(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/route53/route53Provider.go b/providers/route53/route53Provider.go index 475f1d957..4b914d40d 100644 --- a/providers/route53/route53Provider.go +++ b/providers/route53/route53Provider.go @@ -79,6 +79,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseAlias: providers.Cannot("R53 does not provide a generic ALIAS functionality. Use R53_ALIAS instead."), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Can(), providers.CanUseRoute53Alias: providers.Can(), providers.CanUseSRV: providers.Can(), diff --git a/providers/rwth/rwthProvider.go b/providers/rwth/rwthProvider.go index 0467a6cf1..37964a371 100644 --- a/providers/rwth/rwthProvider.go +++ b/providers/rwth/rwthProvider.go @@ -19,6 +19,7 @@ var features = providers.DocumentationNotes{ providers.CanUseAlias: providers.Cannot(), providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Unimplemented("DS records are only supported at the apex and require a different API call that hasn't been implemented yet."), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Cannot(), providers.CanUsePTR: providers.Can("PTR records with empty targets are not supported"), providers.CanUseSRV: providers.Can("SRV records with empty targets are not supported."), diff --git a/providers/softlayer/softlayerProvider.go b/providers/softlayer/softlayerProvider.go index 736828631..2d23ca715 100644 --- a/providers/softlayer/softlayerProvider.go +++ b/providers/softlayer/softlayerProvider.go @@ -24,6 +24,7 @@ type softlayerProvider struct { var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Unimplemented(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseSRV: providers.Can(), } diff --git a/providers/transip/transipProvider.go b/providers/transip/transipProvider.go index e9ac54787..31807e2ba 100644 --- a/providers/transip/transipProvider.go +++ b/providers/transip/transipProvider.go @@ -36,6 +36,7 @@ var features = providers.DocumentationNotes{ providers.CanUseCAA: providers.Can(), providers.CanUseDS: providers.Cannot(), providers.CanUseDSForChildren: providers.Cannot(), + providers.CanUseLOC: providers.Cannot(), providers.CanUseNAPTR: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/vultr/vultrProvider.go b/providers/vultr/vultrProvider.go index e30611922..63dacd281 100644 --- a/providers/vultr/vultrProvider.go +++ b/providers/vultr/vultrProvider.go @@ -30,6 +30,7 @@ var features = providers.DocumentationNotes{ providers.CanGetZones: providers.Can(), providers.CanUseAlias: providers.Cannot(), providers.CanUseCAA: providers.Can(), + providers.CanUseLOC: providers.Cannot(), providers.CanUsePTR: providers.Cannot(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(),