@nictool/dns-resource-record 1.2.4 → 1.3.1
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 +21 -6
- package/README.md +11 -6
- package/index.js +15 -0
- package/lib/tinydns.js +2 -6
- package/package.json +7 -6
- package/rr/apl.js +108 -0
- package/rr/caa.js +3 -8
- package/rr/cert.js +33 -5
- package/rr/cname.js +1 -2
- package/rr/dhcid.js +60 -0
- package/rr/dname.js +1 -2
- package/rr/dnskey.js +6 -12
- package/rr/ds.js +2 -4
- package/rr/hinfo.js +3 -9
- package/rr/hip.js +102 -0
- package/rr/https.js +12 -0
- package/rr/ipseckey.js +4 -9
- package/rr/key.js +2 -4
- package/rr/kx.js +77 -0
- package/rr/loc.js +6 -20
- package/rr/mx.js +3 -7
- package/rr/naptr.js +1 -2
- package/rr/ns.js +2 -6
- package/rr/nsec.js +12 -6
- package/rr/nsec3.js +2 -10
- package/rr/nxt.js +1 -6
- package/rr/openpgpkey.js +2 -3
- package/rr/rp.js +78 -0
- package/rr/rrsig.js +1 -2
- package/rr/smimea.js +20 -19
- package/rr/soa.js +3 -15
- package/rr/spf.js +1 -4
- package/rr/srv.js +3 -7
- package/rr/svcb.js +12 -0
- package/rr/tlsa.js +11 -21
- package/rr/tsig.js +1 -9
- package/rr/txt.js +7 -6
- package/rr/uri.js +1 -2
- package/rr/wks.js +37 -8
- package/rr.js +12 -28
package/rr/srv.js
CHANGED
|
@@ -28,8 +28,7 @@ export default class SRV extends RR {
|
|
|
28
28
|
setTarget(val) {
|
|
29
29
|
if (!val) this.throwHelp(`SRV: target is required`)
|
|
30
30
|
|
|
31
|
-
if (this.isIPv4(val) || this.isIPv6(val))
|
|
32
|
-
this.throwHelp(`SRV: target must be a FQDN`)
|
|
31
|
+
if (this.isIPv4(val) || this.isIPv6(val)) this.throwHelp(`SRV: target must be a FQDN`)
|
|
33
32
|
|
|
34
33
|
this.isFullyQualified('SRV', 'target', val)
|
|
35
34
|
this.isValidHostname('SRV', 'target', val)
|
|
@@ -61,9 +60,7 @@ export default class SRV extends RR {
|
|
|
61
60
|
|
|
62
61
|
if (str[0] === 'S') {
|
|
63
62
|
// patched tinydns with S records
|
|
64
|
-
;[fqdn, addr, port, pri, weight, ttl, ts, loc] = str
|
|
65
|
-
.substring(1)
|
|
66
|
-
.split(':')
|
|
63
|
+
;[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.substring(1).split(':')
|
|
67
64
|
} else {
|
|
68
65
|
// tinydns generic record format
|
|
69
66
|
;[fqdn, n, rdata, ttl, ts, loc] = str.substring(1).split(':')
|
|
@@ -90,8 +87,7 @@ export default class SRV extends RR {
|
|
|
90
87
|
|
|
91
88
|
fromBind(opts) {
|
|
92
89
|
// test.example.com 3600 IN SRV Priority Weight Port Target
|
|
93
|
-
const [owner, ttl, c, type, pri, weight, port, target] =
|
|
94
|
-
opts.bindline.split(/\s+/)
|
|
90
|
+
const [owner, ttl, c, type, pri, weight, port, target] = opts.bindline.split(/\s+/)
|
|
95
91
|
return new SRV({
|
|
96
92
|
owner: owner,
|
|
97
93
|
ttl: parseInt(ttl, 10),
|
package/rr/svcb.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 SVCB extends RR {
|
|
4
6
|
constructor(opts) {
|
|
5
7
|
super(opts)
|
|
@@ -61,4 +63,14 @@ export default class SVCB extends RR {
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/****** EXPORTERS *******/
|
|
66
|
+
|
|
67
|
+
toTinydns() {
|
|
68
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
69
|
+
|
|
70
|
+
return this.getTinydnsGeneric(
|
|
71
|
+
TINYDNS.UInt16toOctal(this.get('priority')) +
|
|
72
|
+
TINYDNS.packDomainName(this.get('target name')) +
|
|
73
|
+
TINYDNS.escapeOctal(dataRe, this.get('params')),
|
|
74
|
+
)
|
|
75
|
+
}
|
|
64
76
|
}
|
package/rr/tlsa.js
CHANGED
|
@@ -9,8 +9,7 @@ export default class TLSA extends RR {
|
|
|
9
9
|
|
|
10
10
|
/****** Resource record specific setters *******/
|
|
11
11
|
setCertificateUsage(val) {
|
|
12
|
-
if (!this.getCertificateUsageOptions().has(val))
|
|
13
|
-
this.throwHelp(`TLSA: certificate usage invalid`)
|
|
12
|
+
if (!this.getCertificateUsageOptions().has(val)) this.throwHelp(`TLSA: certificate usage invalid`)
|
|
14
13
|
|
|
15
14
|
this.set('certificate usage', val)
|
|
16
15
|
}
|
|
@@ -25,8 +24,7 @@ export default class TLSA extends RR {
|
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
setSelector(val) {
|
|
28
|
-
if (!this.getSelectorOptions().has(val))
|
|
29
|
-
this.throwHelp(`TLSA: selector invalid`)
|
|
27
|
+
if (!this.getSelectorOptions().has(val)) this.throwHelp(`TLSA: selector invalid`)
|
|
30
28
|
|
|
31
29
|
this.set('selector', val)
|
|
32
30
|
}
|
|
@@ -39,8 +37,7 @@ export default class TLSA extends RR {
|
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
setMatchingType(val) {
|
|
42
|
-
if (!this.getMatchingTypeOptions().has(val))
|
|
43
|
-
this.throwHelp(`TLSA: matching type`)
|
|
40
|
+
if (!this.getMatchingTypeOptions().has(val)) this.throwHelp(`TLSA: matching type`)
|
|
44
41
|
|
|
45
42
|
this.set('matching type', val)
|
|
46
43
|
}
|
|
@@ -62,12 +59,7 @@ export default class TLSA extends RR {
|
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
getRdataFields(arg) {
|
|
65
|
-
return [
|
|
66
|
-
'certificate usage',
|
|
67
|
-
'selector',
|
|
68
|
-
'matching type',
|
|
69
|
-
'certificate association data',
|
|
70
|
-
]
|
|
62
|
+
return ['certificate usage', 'selector', 'matching type', 'certificate association data']
|
|
71
63
|
}
|
|
72
64
|
|
|
73
65
|
getRFCs() {
|
|
@@ -86,19 +78,17 @@ export default class TLSA extends RR {
|
|
|
86
78
|
|
|
87
79
|
fromBind(opts) {
|
|
88
80
|
// test.example.com 3600 IN TLSA, usage, selector, match, data
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
/^([^\s]+)\s+([0-9]{1,10})\s+(IN)\s+(TLSA)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+(.*?)$/,
|
|
93
|
-
)
|
|
81
|
+
const regex =
|
|
82
|
+
/^(?<owner>\S+)\s+(?<ttl>\d{1,10})\s+(?<cls>IN)\s+(?<type>TLSA)\s+(?<usage>\d+)\s+(?<selector>\d+)\s+(?<matchtype>\d+)\s+(?<cad>.+)$/i
|
|
83
|
+
const match = opts.bindline.trim().match(regex)
|
|
94
84
|
if (!match) this.throwHelp(`unable to parse TLSA: ${opts.bindline}`)
|
|
95
|
-
const
|
|
96
|
-
|
|
85
|
+
const { owner, ttl, cls, type, usage, selector, matchtype, cad } = match.groups
|
|
86
|
+
|
|
97
87
|
return new TLSA({
|
|
98
88
|
owner: this.fullyQualify(owner),
|
|
99
89
|
ttl: parseInt(ttl, 10),
|
|
100
|
-
class:
|
|
101
|
-
type,
|
|
90
|
+
class: cls.toUpperCase(),
|
|
91
|
+
type: type.toUpperCase(),
|
|
102
92
|
'certificate usage': parseInt(usage, 10),
|
|
103
93
|
selector: parseInt(selector, 10),
|
|
104
94
|
'matching type': parseInt(matchtype, 10),
|
package/rr/tsig.js
CHANGED
|
@@ -13,15 +13,7 @@ export default class TSIG extends RR {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
getRdataFields(arg) {
|
|
16
|
-
return [
|
|
17
|
-
'algorithm name',
|
|
18
|
-
'time signed',
|
|
19
|
-
'fudge',
|
|
20
|
-
'mac',
|
|
21
|
-
'original id',
|
|
22
|
-
'error',
|
|
23
|
-
'other',
|
|
24
|
-
]
|
|
16
|
+
return ['algorithm name', 'time signed', 'fudge', 'mac', 'original id', 'error', 'other']
|
|
25
17
|
}
|
|
26
18
|
|
|
27
19
|
getRFCs() {
|
package/rr/txt.js
CHANGED
|
@@ -70,17 +70,18 @@ export default class TXT extends RR {
|
|
|
70
70
|
|
|
71
71
|
fromBind(opts) {
|
|
72
72
|
// test.example.com 3600 IN TXT "..."
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
const regex =
|
|
74
|
+
/^(?<owner>[\S]{1,255})\s+(?<ttl>\d{1,10})\s+(?<cls>IN)\s+(?<type>\w{3})\s+?\s*(?<rdata>.+?)$/i
|
|
75
|
+
const match = opts.bindline.trim().match(regex)
|
|
76
76
|
if (!match) this.throwHelp(`unable to parse TXT: ${opts.bindline}`)
|
|
77
|
-
|
|
77
|
+
|
|
78
|
+
const { owner, ttl, cls, type, rdata } = match.groups
|
|
78
79
|
|
|
79
80
|
return new this.constructor({
|
|
80
81
|
owner,
|
|
81
82
|
ttl: parseInt(ttl, 10),
|
|
82
|
-
class:
|
|
83
|
-
type,
|
|
83
|
+
class: cls,
|
|
84
|
+
type: type.toUpperCase(),
|
|
84
85
|
data: rdata
|
|
85
86
|
.match(/"([^"]+?)"/g)
|
|
86
87
|
.map((s) => s.replace(/^"|"$/g, ''))
|
package/rr/uri.js
CHANGED
|
@@ -46,8 +46,7 @@ export default class URI extends RR {
|
|
|
46
46
|
|
|
47
47
|
fromBind(opts) {
|
|
48
48
|
// test.example.com 3600 IN URI priority, weight, target
|
|
49
|
-
const [owner, ttl, c, type, priority, weight, target] =
|
|
50
|
-
opts.bindline.split(/\s+/)
|
|
49
|
+
const [owner, ttl, c, type, priority, weight, target] = opts.bindline.split(/\s+/)
|
|
51
50
|
return new URI({
|
|
52
51
|
class: c,
|
|
53
52
|
type: type,
|
package/rr/wks.js
CHANGED
|
@@ -1,19 +1,36 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
2
|
|
|
3
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
|
+
|
|
3
5
|
export default class WKS extends RR {
|
|
4
6
|
constructor(opts) {
|
|
5
7
|
super(opts)
|
|
6
|
-
if (opts === null) return
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
/****** Resource record specific setters *******/
|
|
11
|
+
setAddress(val) {
|
|
12
|
+
if (!val) this.throwHelp('WKS: address is required')
|
|
13
|
+
if (!this.isIPv4(val)) this.throwHelp('WKS address must be IPv4')
|
|
14
|
+
this.set('address', val)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setProtocol(val) {
|
|
18
|
+
if (!val) this.throwHelp('WKS: protocol is required')
|
|
19
|
+
const upper = typeof val === 'string' ? val.toUpperCase() : val
|
|
20
|
+
if (!['TCP', 'UDP', 6, 17].includes(upper)) this.throwHelp('WKS protocol must be TCP or UDP')
|
|
21
|
+
this.set('protocol', upper)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setBitMap(val) {
|
|
25
|
+
this.set('bit map', val ?? '')
|
|
26
|
+
}
|
|
10
27
|
|
|
11
28
|
getDescription() {
|
|
12
29
|
return 'Well Known Service'
|
|
13
30
|
}
|
|
14
31
|
|
|
15
32
|
getRdataFields(arg) {
|
|
16
|
-
return ['bit map']
|
|
33
|
+
return ['address', 'protocol', 'bit map']
|
|
17
34
|
}
|
|
18
35
|
|
|
19
36
|
getRFCs() {
|
|
@@ -27,19 +44,31 @@ export default class WKS extends RR {
|
|
|
27
44
|
/****** IMPORTERS *******/
|
|
28
45
|
|
|
29
46
|
fromBind(opts) {
|
|
30
|
-
// test.example.com 3600 IN WKS 192.168.1.1 TCP
|
|
31
|
-
const
|
|
32
|
-
|
|
47
|
+
// test.example.com 3600 IN WKS 192.168.1.1 TCP ftp smtp
|
|
48
|
+
const parts = opts.bindline.split(/\s+/)
|
|
49
|
+
const [owner, ttl, c, type, address, protocol] = parts
|
|
33
50
|
return new WKS({
|
|
34
51
|
owner,
|
|
35
52
|
ttl: parseInt(ttl, 10),
|
|
36
53
|
class: c,
|
|
37
54
|
type,
|
|
38
|
-
address,
|
|
39
|
-
protocol,
|
|
40
|
-
|
|
55
|
+
address,
|
|
56
|
+
protocol,
|
|
57
|
+
'bit map': parts.slice(6).join(' ').trim(),
|
|
41
58
|
})
|
|
42
59
|
}
|
|
43
60
|
|
|
44
61
|
/****** EXPORTERS *******/
|
|
62
|
+
|
|
63
|
+
toTinydns() {
|
|
64
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
65
|
+
const protoMap = { TCP: 6, UDP: 17, 6: 6, 17: 17 }
|
|
66
|
+
const protoNum = protoMap[this.get('protocol')]
|
|
67
|
+
|
|
68
|
+
return this.getTinydnsGeneric(
|
|
69
|
+
TINYDNS.ipv4toOctal(this.get('address')) +
|
|
70
|
+
TINYDNS.UInt8toOctal(protoNum) +
|
|
71
|
+
TINYDNS.escapeOctal(dataRe, this.get('bit map')),
|
|
72
|
+
)
|
|
73
|
+
}
|
|
45
74
|
}
|
package/rr.js
CHANGED
|
@@ -20,8 +20,7 @@ export default class RR extends Map {
|
|
|
20
20
|
|
|
21
21
|
for (const f of this.getFields('rdata')) {
|
|
22
22
|
const fnName = `set${this.ucFirst(f)}`
|
|
23
|
-
if (this[fnName] === undefined)
|
|
24
|
-
this.throwHelp(`Missing ${fnName} in class ${this.get('type')}`)
|
|
23
|
+
if (this[fnName] === undefined) this.throwHelp(`Missing ${fnName} in class ${this.get('type')}`)
|
|
25
24
|
this[fnName](opts[f])
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -77,9 +76,7 @@ export default class RR extends Map {
|
|
|
77
76
|
if (n === undefined) this.throwHelp(`owner is required`)
|
|
78
77
|
|
|
79
78
|
if (n.length < 1 || n.length > 255)
|
|
80
|
-
this.throwHelp(
|
|
81
|
-
'Domain names must have 1-255 octets (characters): RFC 2181',
|
|
82
|
-
)
|
|
79
|
+
this.throwHelp('Domain names must have 1-255 octets (characters): RFC 2181')
|
|
83
80
|
|
|
84
81
|
this.isFullyQualified(this.constructor.name, 'owner', n)
|
|
85
82
|
this.hasValidLabels(n)
|
|
@@ -100,8 +97,7 @@ export default class RR extends Map {
|
|
|
100
97
|
this.throwHelp('TTL is required, no default available')
|
|
101
98
|
}
|
|
102
99
|
|
|
103
|
-
if (typeof t !== 'number')
|
|
104
|
-
this.throwHelp(`TTL must be numeric (${typeof t})`)
|
|
100
|
+
if (typeof t !== 'number') this.throwHelp(`TTL must be numeric (${typeof t})`)
|
|
105
101
|
|
|
106
102
|
// RFC 1035, 2181
|
|
107
103
|
this.is32bitInt(this.get('type'), 'TTL', t)
|
|
@@ -209,8 +205,7 @@ export default class RR extends Map {
|
|
|
209
205
|
|
|
210
206
|
if (zone_opts.hide?.origin && zone_opts.origin) {
|
|
211
207
|
if (fqdn === zone_opts.origin) return '@'
|
|
212
|
-
if (fqdn.endsWith(zone_opts.origin))
|
|
213
|
-
return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1)
|
|
208
|
+
if (fqdn.endsWith(zone_opts.origin)) return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1)
|
|
214
209
|
}
|
|
215
210
|
|
|
216
211
|
return fqdn
|
|
@@ -232,9 +227,7 @@ export default class RR extends Map {
|
|
|
232
227
|
}
|
|
233
228
|
|
|
234
229
|
getTinydnsPostamble() {
|
|
235
|
-
return ['ttl', 'timestamp', 'location']
|
|
236
|
-
.map((f) => this.getEmpty(f))
|
|
237
|
-
.join(':')
|
|
230
|
+
return ['ttl', 'timestamp', 'location'].map((f) => this.getEmpty(f)).join(':')
|
|
238
231
|
}
|
|
239
232
|
|
|
240
233
|
hasValidLabels(hostname) {
|
|
@@ -258,9 +251,7 @@ export default class RR extends Map {
|
|
|
258
251
|
)
|
|
259
252
|
return true
|
|
260
253
|
|
|
261
|
-
this.throwHelp(
|
|
262
|
-
`${type} ${field} must be a 8-bit integer (in the range 0-255)`,
|
|
263
|
-
)
|
|
254
|
+
this.throwHelp(`${type} ${field} must be a 8-bit integer (in the range 0-255)`)
|
|
264
255
|
}
|
|
265
256
|
|
|
266
257
|
is16bitInt(type, field, value) {
|
|
@@ -272,9 +263,7 @@ export default class RR extends Map {
|
|
|
272
263
|
)
|
|
273
264
|
return true
|
|
274
265
|
|
|
275
|
-
this.throwHelp(
|
|
276
|
-
`${type} ${field} must be a 16-bit integer (in the range 0-65535)`,
|
|
277
|
-
)
|
|
266
|
+
this.throwHelp(`${type} ${field} must be a 16-bit integer (in the range 0-65535)`)
|
|
278
267
|
}
|
|
279
268
|
|
|
280
269
|
is32bitInt(type, field, value) {
|
|
@@ -286,9 +275,7 @@ export default class RR extends Map {
|
|
|
286
275
|
)
|
|
287
276
|
return true
|
|
288
277
|
|
|
289
|
-
this.throwHelp(
|
|
290
|
-
`${type} ${field} must be a 32-bit integer (in the range 0-2147483647)`,
|
|
291
|
-
)
|
|
278
|
+
this.throwHelp(`${type} ${field} must be a 32-bit integer (in the range 0-2147483647)`)
|
|
292
279
|
}
|
|
293
280
|
|
|
294
281
|
isQuoted(val) {
|
|
@@ -306,9 +293,7 @@ export default class RR extends Map {
|
|
|
306
293
|
if (!allowed.test(hostname)) return true
|
|
307
294
|
|
|
308
295
|
const matches = allowed.exec(hostname)
|
|
309
|
-
this.throwHelp(
|
|
310
|
-
`${type}, ${field} has invalid hostname character (${matches[0]})`,
|
|
311
|
-
)
|
|
296
|
+
this.throwHelp(`${type}, ${field} has invalid hostname character (${matches[0]})`)
|
|
312
297
|
}
|
|
313
298
|
|
|
314
299
|
isIPv4(string) {
|
|
@@ -330,10 +315,9 @@ export default class RR extends Map {
|
|
|
330
315
|
|
|
331
316
|
toMaraDNS() {
|
|
332
317
|
const type = this.get('type')
|
|
333
|
-
const supportedTypes =
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
)
|
|
318
|
+
const supportedTypes = 'A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC'.split(
|
|
319
|
+
/\s+/g,
|
|
320
|
+
)
|
|
337
321
|
if (!supportedTypes.includes(type)) return this.toMaraGeneric()
|
|
338
322
|
return `${this.get('owner')}\t+${this.get('ttl')}\t${type}\t${this.getRdataFields()
|
|
339
323
|
.map((f) => this.getQuoted(f))
|