@nictool/dns-resource-record 1.2.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,26 +4,44 @@ Notable changes to this project are documented in this file.
4
4
 
5
5
  #### Unreleased
6
6
 
7
+ ### [1.3.0] - 2026-03-01
8
+
9
+ - feat: add toTinydns for CERT, HTTPS, NSEC, SMIMEA, SVCB, WKS #51
10
+ - feat: add APL, KX, DHCID, HIP, and RP RR types #50
11
+ - feat: add WKS record setters, rdata fields, and tests #49
12
+ - style: wrap lines to 110 (was 80) chars
13
+ - tlsa: require cert assocc data
14
+ - deps(\*): update to latest, eslint 9 -> 10
15
+
16
+ ### [1.2.4] - 2025-10-06
17
+
18
+ - rr: rename ucfirst -> ucFirst
19
+ - rr: setTTL was checking this.owner (copy/paste error)
20
+ - rr: improved throwHelp message formatting
21
+ - aaaa: compress & expand returns lower case
22
+ - caa, dnskey, ds, ipseckey, key, naptr, rrsig, smimea, sshfp, tlsa: refactored opts as JS maps
23
+ - deps: bump to latest versions
24
+
7
25
  ### [1.2.3] - 2025-04-14
8
26
 
9
27
  - test(\*): fully qualify node modules
10
28
  - feat(rr.isIPv?): added regexes to validate format
11
29
  - dep(node:{net|util): remove, for browser compatiblity
12
30
  - doc(CONTRIBUTORS.md): added
13
- - ci: disable codeql schedule (#45)
31
+ - ci: disable codeql schedule #45
14
32
 
15
33
  ### [1.2.2] - 2024-11-17
16
34
 
17
35
  - dep(eslint): update to v9 & config
18
36
  - chore: tighten up fromBind regex
19
- - packaging tweaks (#43)
37
+ - packaging tweaks #43
20
38
 
21
39
  ### [1.2.1] - 2024-03-10
22
40
 
23
41
  - fix(nsec3param): fixed setHash fname typo
24
- - feat(SVCB,HTTPS): add record support (#29)
42
+ - feat(SVCB,HTTPS): add record support #29
25
43
  - feat(OPENGPGPKEY): improved bindline parser, added test
26
- - feat(throwHelp): far more useful error messages (#41)
44
+ - feat(throwHelp): far more useful error messages #41
27
45
  - feat(A,MX,AAAA,CAA,IPSECKEY): added getCanonical
28
46
 
29
47
  ### [1.2.0] - 2024-03-07
@@ -31,7 +49,7 @@ Notable changes to this project are documented in this file.
31
49
  - feat(index): export typeMap (lookup table for type to id)
32
50
  - feat(NXT): added bind support
33
51
  - feat(TSIG, WKS): added stub class
34
- - doc(README): move synopsis section into table (#38)
52
+ - doc(README): move synopsis section into table #38
35
53
  - chore(style): set up prettier
36
54
 
37
55
  ### [1.1.6] - 2022-06-21
@@ -310,6 +328,8 @@ Notable changes to this project are documented in this file.
310
328
  [1.1.8]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.8
311
329
  [1.1.7]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.7
312
330
  [1.2.0]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.0
313
- [1.2.1]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.2.1
331
+ [1.2.1]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.1
314
332
  [1.2.2]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.2
315
- [1.2.3]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.2.3
333
+ [1.2.3]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.3
334
+ [1.2.4]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.4
335
+ [1.3.0]: https://github.com/NicTool/dns-resource-record/releases/tag/1.3.0
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # dns-resource-record
5
5
 
6
- DNS resource record parser, validator, importer, and exporter.
6
+ DNS resource record parser, validator, importer, and exporter for node.js & browsers.
7
7
 
8
8
  ## SYNOPSIS
9
9
 
@@ -181,7 +181,7 @@ Consider this a "running with scissors" mode.
181
181
 
182
182
  ## Supported Records
183
183
 
184
- This module intends to include support for all current (ie, not officially deprecated) DNS RRs **and** all RRs that are in active use on the internet.
184
+ This module intends to support all current (ie, not officially deprecated) DNS RRs **and** all RRs that are in active use on the internet.
185
185
 
186
186
  PRs are welcome, especially PRs with tests.
187
187
 
@@ -189,39 +189,44 @@ PRs are welcome, especially PRs with tests.
189
189
  | :------------: | :----------------: | :----------------: | :----------------: | :----------------: |
190
190
  | **A** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
191
191
  | **AAAA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
192
+ | **APL** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
192
193
  | **CAA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
193
- | **CERT** | :white_check_mark: | | :white_check_mark: | |
194
+ | **CERT** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
194
195
  | **CNAME** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
196
+ | **DHCID** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
195
197
  | **DNAME** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
196
198
  | **DNSKEY** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
197
199
  | **DS** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
198
200
  | **HINFO** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
199
- | **HTTPS** | | | | |
201
+ | **HIP** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
202
+ | **HTTPS** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
200
203
  | **IPSECKEY** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
201
204
  | **KEY** | | | | |
205
+ | **KX** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
202
206
  | **LOC** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
203
207
  | **MX** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
204
208
  | **NAPTR** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
205
209
  | **NS** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
206
- | **NSEC** | :white_check_mark: | | :white_check_mark: | |
210
+ | **NSEC** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
207
211
  | **NSEC3** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
208
212
  | **NSEC3PARAM** | | | | |
209
213
  | **NXT** | | | | |
210
214
  | **OPENPGPKEY** | | | | |
211
215
  | **PTR** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
216
+ | **RP** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
212
217
  | **RRSIG** | | | | |
213
218
  | **SIG** | | | | |
214
- | **SMIMEA** | :white_check_mark: | | :white_check_mark: | |
219
+ | **SMIMEA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
215
220
  | **SOA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
216
221
  | **SPF** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
217
222
  | **SRV** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
218
223
  | **SSHFP** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
219
- | **SVCB** | | | | |
224
+ | **SVCB** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
220
225
  | **TLSA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
221
226
  | **TSIG** | | | | |
222
227
  | **TXT** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
223
228
  | **URI** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
224
- | **WKS** | | | | |
229
+ | **WKS** | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
225
230
 
226
231
  ## TIPS
227
232
 
@@ -244,17 +249,6 @@ PRs are welcome, especially PRs with tests.
244
249
 
245
250
  ## TODO
246
251
 
247
- - [x] Change all IPs to use [RFC example/doc](https://en.wikipedia.org/wiki/Reserved_IP_addresses) address space
248
- - [x] change all domains to use reserved doc names
249
- - [x] import tests from nictool/server/t/12_records.t
250
- - [x] add defaults for empty values like TTL
251
- - [x] DNSSEC RRs: DS, NSEC, NSEC3, NSEC3PARAM, RRSIG
252
- - [x] CERT RRs: CERT, KEY, SIG, OPENPGPKEY
253
- - [x] RFC 4034: if the type of RR is NS, MD, MF, CNAME, SOA, MB,
254
- MG, MR, PTR, HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT,
255
- NAPTR, KX, SRV, DNAME, A6, RRSIG, or NSEC, all uppercase
256
- letters in the DNS names contained within the RDATA are replaced by the lowercase letters;
257
- - [x] LOC record ingest/out isn't consistent with API
258
252
  - [ ] export a web page for each RR type
259
253
 
260
254
  ## DEVELOP
package/index.js CHANGED
@@ -3,16 +3,20 @@ const typeMap = {}
3
3
  import RR from './rr.js'
4
4
  import A from './rr/a.js'
5
5
  import AAAA from './rr/aaaa.js'
6
+ import APL from './rr/apl.js'
6
7
  import CAA from './rr/caa.js'
7
8
  import CERT from './rr/cert.js'
8
9
  import CNAME from './rr/cname.js'
10
+ import DHCID from './rr/dhcid.js'
9
11
  import DNAME from './rr/dname.js'
10
12
  import DNSKEY from './rr/dnskey.js'
11
13
  import DS from './rr/ds.js'
12
14
  import HINFO from './rr/hinfo.js'
15
+ import HIP from './rr/hip.js'
13
16
  import HTTPS from './rr/https.js'
14
17
  import IPSECKEY from './rr/ipseckey.js'
15
18
  import KEY from './rr/key.js'
19
+ import KX from './rr/kx.js'
16
20
  import LOC from './rr/loc.js'
17
21
  import MX from './rr/mx.js'
18
22
  import NAPTR from './rr/naptr.js'
@@ -23,6 +27,7 @@ import NSEC3PARAM from './rr/nsec3param.js'
23
27
  import NXT from './rr/nxt.js'
24
28
  import OPENPGPKEY from './rr/openpgpkey.js'
25
29
  import PTR from './rr/ptr.js'
30
+ import RP from './rr/rp.js'
26
31
  import RRSIG from './rr/rrsig.js'
27
32
  import SIG from './rr/sig.js'
28
33
  import SMIMEA from './rr/smimea.js'
@@ -42,16 +47,20 @@ export default RR
42
47
  export {
43
48
  A,
44
49
  AAAA,
50
+ APL,
45
51
  CAA,
46
52
  CERT,
47
53
  CNAME,
54
+ DHCID,
48
55
  DNAME,
49
56
  DNSKEY,
50
57
  DS,
51
58
  HINFO,
59
+ HIP,
52
60
  HTTPS,
53
61
  IPSECKEY,
54
62
  KEY,
63
+ KX,
55
64
  LOC,
56
65
  MX,
57
66
  NAPTR,
@@ -62,6 +71,7 @@ export {
62
71
  NXT,
63
72
  OPENPGPKEY,
64
73
  PTR,
74
+ RP,
65
75
  RRSIG,
66
76
  SIG,
67
77
  SMIMEA,
@@ -81,16 +91,20 @@ export {
81
91
  for (const c of [
82
92
  A,
83
93
  AAAA,
94
+ APL,
84
95
  CAA,
85
96
  CERT,
86
97
  CNAME,
98
+ DHCID,
87
99
  DNAME,
88
100
  DNSKEY,
89
101
  DS,
90
102
  HINFO,
103
+ HIP,
91
104
  HTTPS,
92
105
  IPSECKEY,
93
106
  KEY,
107
+ KX,
94
108
  LOC,
95
109
  MX,
96
110
  NAPTR,
@@ -101,6 +115,7 @@ for (const c of [
101
115
  NXT,
102
116
  OPENPGPKEY,
103
117
  PTR,
118
+ RP,
104
119
  RRSIG,
105
120
  SIG,
106
121
  SMIMEA,
package/lib/tinydns.js CHANGED
@@ -29,9 +29,7 @@ export function escapeOctal(re, str) {
29
29
 
30
30
  export function octalToChar(str) {
31
31
  // relace instances of \NNN with ASCII
32
- return str.replace(octalRe, (o) =>
33
- String.fromCharCode(parseInt(o.substring(1), 8)),
34
- )
32
+ return str.replace(octalRe, (o) => String.fromCharCode(parseInt(o.substring(1), 8)))
35
33
  }
36
34
 
37
35
  export function octalToHex(str) {
@@ -181,9 +179,7 @@ export function base64toOctal(str) {
181
179
  const bytes = Buffer.from(str, 'base64')
182
180
  let escaped = ''
183
181
  for (const b of bytes) {
184
- escaped += /[A-Za-z0-9\-.]/.test(String.fromCharCode(b))
185
- ? String.fromCharCode(b)
186
- : UInt8toOctal(b)
182
+ escaped += /[A-Za-z0-9\-.]/.test(String.fromCharCode(b)) ? String.fromCharCode(b) : UInt8toOctal(b)
187
183
  }
188
184
  return escaped
189
185
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nictool/dns-resource-record",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "DNS Resource Records",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -19,7 +19,8 @@
19
19
  "prettier:fix": "npx prettier --ignore-path .gitignore --write .",
20
20
  "test": "npx mocha",
21
21
  "versions": "npx dependency-version-checker check",
22
- "watch": "npm run test -- --watch"
22
+ "watch": "npm run test -- --watch",
23
+ "versions:fix": "npx dependency-version-checker update"
23
24
  },
24
25
  "repository": {
25
26
  "type": "git",
@@ -45,12 +46,13 @@
45
46
  },
46
47
  "homepage": "https://github.com/NicTool/dns-resource-record#readme",
47
48
  "devDependencies": {
48
- "@eslint/js": "^10.0.0",
49
- "eslint": "^9.15.0",
50
- "globals": "^16.0.0",
51
- "mocha": "^11.2.2"
49
+ "@eslint/js": "^10.0.1",
50
+ "eslint": "^10.0.2",
51
+ "globals": "^17.4.0",
52
+ "mocha": "^11.7.5"
52
53
  },
53
54
  "prettier": {
55
+ "printWidth": 110,
54
56
  "semi": false,
55
57
  "singleQuote": true,
56
58
  "trailingComma": "all"
package/rr/aaaa.js CHANGED
@@ -15,7 +15,7 @@ export default class AAAA extends RR {
15
15
  }
16
16
 
17
17
  getCompressed(val) {
18
- this.compress(val || this.get('address'))
18
+ return this.compress(val || this.get('address'))
19
19
  }
20
20
 
21
21
  getDescription() {
@@ -112,12 +112,12 @@ export default class AAAA extends RR {
112
112
 
113
113
  for (const re of mostConsecutiveZeros) {
114
114
  if (re.test(r)) {
115
- r = r.replace(re, '::')
115
+ r = r.replace(re, '::') // 4.2
116
116
  break
117
117
  }
118
118
  }
119
119
 
120
- return r
120
+ return r.toLowerCase() // 4.3
121
121
  }
122
122
 
123
123
  expand(val, delimiter) {
@@ -134,11 +134,12 @@ export default class AAAA extends RR {
134
134
  .split(':')
135
135
  .map((s) => s.padStart(4, 0))
136
136
  .join(delimiter)
137
+ .toLowerCase()
137
138
  }
138
139
 
139
140
  /****** EXPORTERS *******/
140
141
  toBind(zone_opts) {
141
- return `${this.getPrefix(zone_opts)}\t${this.compress(this.get('address'))}\n`
142
+ return `${this.getPrefix(zone_opts)}\t${this.getCompressed()}\n`
142
143
  }
143
144
 
144
145
  toTinydns() {
package/rr/apl.js ADDED
@@ -0,0 +1,108 @@
1
+ import RR from '../rr.js'
2
+
3
+ import * as TINYDNS from '../lib/tinydns.js'
4
+
5
+ export default class APL extends RR {
6
+ constructor(opts) {
7
+ super(opts)
8
+ }
9
+
10
+ /****** Resource record specific setters *******/
11
+ setAplRdata(val) {
12
+ if (!val) this.throwHelp('APL: apl rdata is required')
13
+ // apl rdata is a list of address prefix list items, e.g.:
14
+ // 1:192.0.2.0/24 !1:192.0.2.64/28 2:2001:db8::/32
15
+ this.set('apl rdata', val)
16
+ }
17
+
18
+ getDescription() {
19
+ return 'Address Prefix List'
20
+ }
21
+
22
+ getRdataFields(arg) {
23
+ return ['apl rdata']
24
+ }
25
+
26
+ getRFCs() {
27
+ return [3123]
28
+ }
29
+
30
+ getTypeId() {
31
+ return 42
32
+ }
33
+
34
+ getCanonical() {
35
+ return {
36
+ owner: 'example.com.',
37
+ ttl: 3600,
38
+ class: 'IN',
39
+ type: 'APL',
40
+ 'apl rdata': '1:192.0.2.0/24 !1:192.0.2.64/28 2:2001:db8::/32',
41
+ }
42
+ }
43
+
44
+ /****** IMPORTERS *******/
45
+ fromBind(opts) {
46
+ // test.example.com 3600 IN APL {[!]afi:address/prefix}*
47
+ const parts = opts.bindline.split(/\s+/)
48
+ const [owner, ttl, c, type] = parts
49
+ return new APL({
50
+ owner,
51
+ ttl: parseInt(ttl, 10),
52
+ class: c,
53
+ type,
54
+ 'apl rdata': parts.slice(4).join(' ').trim(),
55
+ })
56
+ }
57
+
58
+ /****** EXPORTERS *******/
59
+ toTinydns() {
60
+ return this.getTinydnsGeneric(
61
+ this.get('apl rdata')
62
+ .split(/\s+/)
63
+ .map((item) => {
64
+ const neg = item.startsWith('!')
65
+ const bare = neg ? item.slice(1) : item
66
+ const colonIdx = bare.indexOf(':')
67
+ const afi = parseInt(bare.slice(0, colonIdx), 10)
68
+ const rest = bare.slice(colonIdx + 1)
69
+ const slashIdx = rest.lastIndexOf('/')
70
+ const addr = rest.slice(0, slashIdx)
71
+ const prefix = parseInt(rest.slice(slashIdx + 1), 10)
72
+
73
+ let addrBytes
74
+ if (afi === 1) {
75
+ addrBytes = Buffer.from(addr.split('.').map((n) => parseInt(n, 10)))
76
+ } else {
77
+ const dblIdx = addr.indexOf('::')
78
+ let groups
79
+ if (dblIdx !== -1) {
80
+ const left = addr
81
+ .slice(0, dblIdx)
82
+ .split(':')
83
+ .filter((s) => s !== '')
84
+ const right = addr
85
+ .slice(dblIdx + 2)
86
+ .split(':')
87
+ .filter((s) => s !== '')
88
+ groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right]
89
+ } else {
90
+ groups = addr.split(':')
91
+ }
92
+ addrBytes = Buffer.from(groups.map((g) => g.padStart(4, '0')).join(''), 'hex')
93
+ }
94
+
95
+ let len = addrBytes.length
96
+ while (len > 0 && addrBytes[len - 1] === 0) len--
97
+ const afdPart = addrBytes.slice(0, len)
98
+
99
+ let r = TINYDNS.UInt16toOctal(afi)
100
+ r += TINYDNS.UInt8toOctal(prefix)
101
+ r += TINYDNS.UInt8toOctal((neg ? 0x80 : 0) | afdPart.length)
102
+ for (const b of afdPart) r += TINYDNS.UInt8toOctal(b)
103
+ return r
104
+ })
105
+ .join(''),
106
+ )
107
+ }
108
+ }
package/rr/caa.js CHANGED
@@ -10,25 +10,34 @@ export default class CAA extends RR {
10
10
  setFlags(val) {
11
11
  this.is8bitInt('CAA', 'flags', val)
12
12
 
13
- if (![0, 128].includes(val)) {
13
+ if (!this.getFlagsOptions().has(val)) {
14
14
  this.throwHelp(`CAA flags ${val} not recognized`)
15
15
  }
16
16
 
17
17
  this.set('flags', val)
18
18
  }
19
19
 
20
+ getFlagsOptions() {
21
+ return new Map([
22
+ [0, 'Non Critical'],
23
+ [128, 'Critical'],
24
+ ])
25
+ }
26
+
20
27
  setTag(val) {
21
28
  if (typeof val !== 'string' || val.length < 1 || /[^a-z0-9]/.test(val))
22
- this.throwHelp(
23
- `CAA tag must be a sequence of ASCII letters and numbers in lowercase`,
24
- )
29
+ this.throwHelp(`CAA tag must be a sequence of ASCII letters and numbers in lowercase`)
25
30
 
26
- if (!['issue', 'issuewild', 'iodef'].includes(val)) {
31
+ if (!this.getTagOptions().has(val)) {
27
32
  this.throwHelp(`CAA tag ${val} not recognized`)
28
33
  }
29
34
  this.set('tag', val)
30
35
  }
31
36
 
37
+ getTagOptions() {
38
+ return new Map([['issue'], ['issuewild'], ['iodef']])
39
+ }
40
+
32
41
  setValue(val) {
33
42
  // either (2) a quoted string or
34
43
  // (1) a contiguous set of characters without interior spaces
@@ -108,11 +117,8 @@ export default class CAA extends RR {
108
117
 
109
118
  fromBind(opts) {
110
119
  // test.example.com 3600 IN CAA flags, tags, value
111
- const fields = opts.bindline
112
- .trim()
113
- .match(
114
- /^([\S]+)\s+([0-9]{1,10})\s+(IN)\s+(CAA)\s+([0-9]+)\s+(\w+)\s+("[^"]+"|[\S]+?)$/i,
115
- )
120
+ const regex = /^([\S]+)\s+([0-9]{1,10})\s+(IN)\s+(CAA)\s+([0-9]+)\s+(\w+)\s+("[^"]+"|[\S]+?)$/i
121
+ const fields = opts.bindline.trim().match(regex)
116
122
  if (!fields) this.throwHelp(`unable to parse: ${opts.bindline}`)
117
123
 
118
124
  const [owner, ttl, c, type, flags, tag, value] = fields.slice(1)
package/rr/cert.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import RR from '../rr.js'
2
2
 
3
+ import * as TINYDNS from '../lib/tinydns.js'
4
+
3
5
  export default class CERT extends RR {
4
6
  constructor(opts) {
5
7
  super(opts)
@@ -14,6 +16,24 @@ export default class CERT extends RR {
14
16
  this.set('cert type', val)
15
17
  }
16
18
 
19
+ getCertTypeValue(val) {
20
+ if (typeof val === 'number') return val
21
+ const types = {
22
+ PKIX: 1,
23
+ SPKI: 2,
24
+ PGP: 3,
25
+ IPKIX: 4,
26
+ ISPKI: 5,
27
+ IPGP: 6,
28
+ ACPKIX: 7,
29
+ IACPKIX: 8,
30
+ URI: 253,
31
+ OID: 254,
32
+ }
33
+ if (Object.hasOwn(types, val)) return types[val]
34
+ this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`)
35
+ }
36
+
17
37
  setKeyTag(val) {
18
38
  // The key tag field is the 16-bit value
19
39
  // The key tag field is represented as an unsigned decimal integer.
@@ -57,16 +77,13 @@ export default class CERT extends RR {
57
77
 
58
78
  fromBind(opts) {
59
79
  // test.example.com 3600 IN CERT certtype, keytag, algo, cert
60
- const [owner, ttl, c, type, certtype, keytag, algo, certificate] =
61
- opts.bindline.split(/\s+/)
80
+ const [owner, ttl, c, type, certtype, keytag, algo, certificate] = opts.bindline.split(/\s+/)
62
81
  return new CERT({
63
82
  owner,
64
83
  ttl: parseInt(ttl, 10),
65
84
  class: c,
66
85
  type,
67
- 'cert type': /^[0-9]+$/.test(certtype)
68
- ? parseInt(certtype, 10)
69
- : certtype,
86
+ 'cert type': /^[0-9]+$/.test(certtype) ? parseInt(certtype, 10) : certtype,
70
87
  'key tag': parseInt(keytag, 10),
71
88
  algorithm: parseInt(algo, 10),
72
89
  certificate,
@@ -74,4 +91,15 @@ export default class CERT extends RR {
74
91
  }
75
92
 
76
93
  /****** EXPORTERS *******/
94
+
95
+ toTinydns() {
96
+ const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
97
+
98
+ return this.getTinydnsGeneric(
99
+ TINYDNS.UInt16toOctal(this.getCertTypeValue(this.get('cert type'))) +
100
+ TINYDNS.UInt16toOctal(this.get('key tag')) +
101
+ TINYDNS.UInt8toOctal(this.get('algorithm')) +
102
+ TINYDNS.escapeOctal(dataRe, this.get('certificate')),
103
+ )
104
+ }
77
105
  }
package/rr/cname.js CHANGED
@@ -12,8 +12,7 @@ export default class CNAME extends RR {
12
12
 
13
13
  if (!val) this.throwHelp('CNAME: cname is required')
14
14
 
15
- if (this.isIPv4(val) || this.isIPv6(val))
16
- this.throwHelp(`CNAME: cname must be a FQDN: RFC 2181`)
15
+ if (this.isIPv4(val) || this.isIPv6(val)) this.throwHelp(`CNAME: cname must be a FQDN: RFC 2181`)
17
16
 
18
17
  if (!this.isFullyQualified('CNAME', 'cname', val)) return
19
18
  if (!this.isValidHostname('CNAME', 'cname', val)) return
package/rr/dhcid.js ADDED
@@ -0,0 +1,60 @@
1
+ import RR from '../rr.js'
2
+
3
+ import * as TINYDNS from '../lib/tinydns.js'
4
+
5
+ export default class DHCID extends RR {
6
+ constructor(opts) {
7
+ super(opts)
8
+ }
9
+
10
+ /****** Resource record specific setters *******/
11
+ setData(val) {
12
+ if (!val) this.throwHelp('DHCID: data is required')
13
+ this.set('data', val)
14
+ }
15
+
16
+ getDescription() {
17
+ return 'DHCP Identifier'
18
+ }
19
+
20
+ getRdataFields(arg) {
21
+ return ['data']
22
+ }
23
+
24
+ getRFCs() {
25
+ return [4701]
26
+ }
27
+
28
+ getTypeId() {
29
+ return 49
30
+ }
31
+
32
+ getCanonical() {
33
+ return {
34
+ owner: 'host.example.com.',
35
+ ttl: 3600,
36
+ class: 'IN',
37
+ type: 'DHCID',
38
+ data: 'AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=',
39
+ }
40
+ }
41
+
42
+ /****** IMPORTERS *******/
43
+ fromBind(opts) {
44
+ // host.example.com 3600 IN DHCID <base64data>
45
+ const parts = opts.bindline.split(/\s+/)
46
+ const [owner, ttl, c, type] = parts
47
+ return new DHCID({
48
+ owner,
49
+ ttl: parseInt(ttl, 10),
50
+ class: c,
51
+ type,
52
+ data: parts.slice(4).join(''),
53
+ })
54
+ }
55
+
56
+ /****** EXPORTERS *******/
57
+ toTinydns() {
58
+ return this.getTinydnsGeneric(TINYDNS.base64toOctal(this.get('data')))
59
+ }
60
+ }
package/rr/dname.js CHANGED
@@ -10,8 +10,7 @@ export default class DNAME extends RR {
10
10
  setTarget(val) {
11
11
  if (!val) this.throwHelp('DNAME: target is required')
12
12
 
13
- if (this.isIPv4(val) || this.isIPv6(val))
14
- this.throwHelp(`DNAME: target must be a domain name`)
13
+ if (this.isIPv4(val) || this.isIPv6(val)) this.throwHelp(`DNAME: target must be a domain name`)
15
14
 
16
15
  this.isFullyQualified('DNAME', 'target', val)
17
16
  this.isValidHostname('DNAME', 'target', val)