@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 +27 -7
- package/README.md +13 -19
- package/index.js +15 -0
- package/lib/tinydns.js +2 -6
- package/package.json +8 -6
- package/rr/aaaa.js +5 -4
- package/rr/apl.js +108 -0
- package/rr/caa.js +16 -10
- 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 +38 -11
- package/rr/ds.js +14 -5
- package/rr/hinfo.js +3 -9
- package/rr/hip.js +102 -0
- package/rr/https.js +12 -0
- package/rr/ipseckey.js +22 -9
- package/rr/key.js +15 -5
- package/rr/kx.js +77 -0
- package/rr/loc.js +6 -20
- package/rr/mx.js +3 -7
- package/rr/naptr.js +5 -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 +13 -3
- package/rr/smimea.js +44 -17
- package/rr/soa.js +3 -15
- package/rr/spf.js +1 -4
- package/rr/srv.js +3 -7
- package/rr/sshfp.js +20 -3
- package/rr/svcb.js +12 -0
- package/rr/tlsa.js +35 -19
- 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 +16 -32
package/rr/dnskey.js
CHANGED
|
@@ -12,34 +12,63 @@ export default class DNSKEY extends RR {
|
|
|
12
12
|
// a 2 octet Flags Field
|
|
13
13
|
this.is16bitInt('DNSKEY', 'flags', val)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (!this.getFlagsOptions().has(val)) {
|
|
16
|
+
this.throwHelp(`DNSKEY: flags must be in the set: ${this.getFlagsOptions()}`)
|
|
17
|
+
}
|
|
17
18
|
|
|
18
19
|
this.set('flags', val)
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
// possible values are: 0, 256, and 257; RFC 4034
|
|
23
|
+
getFlagsOptions() {
|
|
24
|
+
return new Map([[0], [256], [257]])
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
setProtocol(val) {
|
|
22
28
|
// 1 octet
|
|
23
29
|
this.is8bitInt('DNSKEY', 'protocol', val)
|
|
24
30
|
|
|
25
31
|
// The Protocol Field MUST be represented as an unsigned decimal integer with a value of 3.
|
|
26
|
-
if (!
|
|
32
|
+
if (!this.getProtocolOptions().has(val)) this.throwHelp(`DNSKEY: protocol invalid`)
|
|
27
33
|
|
|
28
34
|
this.set('protocol', val)
|
|
29
35
|
}
|
|
30
36
|
|
|
37
|
+
getProtocolOptions() {
|
|
38
|
+
return new Map([[3]])
|
|
39
|
+
}
|
|
40
|
+
|
|
31
41
|
setAlgorithm(val) {
|
|
32
42
|
// 1 octet
|
|
33
43
|
this.is8bitInt('DNSKEY', 'algorithm', val)
|
|
34
44
|
|
|
35
45
|
// https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
|
36
|
-
|
|
37
|
-
if (![...Array(16).keys(), 253, 254].includes(val))
|
|
38
|
-
console.error(`DNSKEY: algorithm (${val}) not recognized`)
|
|
46
|
+
if (!this.getAlgorithmOptions().has(val)) console.error(`DNSKEY: algorithm (${val}) not recognized`)
|
|
39
47
|
|
|
40
48
|
this.set('algorithm', val)
|
|
41
49
|
}
|
|
42
50
|
|
|
51
|
+
getAlgorithmOptions() {
|
|
52
|
+
return new Map([
|
|
53
|
+
[1, 'RSA/MD5 (DEPRECATED)'],
|
|
54
|
+
[2, 'DH'],
|
|
55
|
+
[3, 'DSA/SHA-1'],
|
|
56
|
+
[4, 'EC'],
|
|
57
|
+
[5, 'RSA/SHA-1'],
|
|
58
|
+
[6, 'DSA-NSEC3-SHA1'],
|
|
59
|
+
[7, 'RSASHA1-NSEC3-SHA1'],
|
|
60
|
+
[8, 'RSA/SHA-256'],
|
|
61
|
+
[9, ''],
|
|
62
|
+
[10, 'RSA/SHA-512'],
|
|
63
|
+
[13, 'ECDSA Curve P-256 with SHA-256'],
|
|
64
|
+
[14, 'ECDSA Curve P-384 with SHA-384'],
|
|
65
|
+
[15, 'Ed25519'],
|
|
66
|
+
[16, 'Ed448'],
|
|
67
|
+
[253],
|
|
68
|
+
[254],
|
|
69
|
+
])
|
|
70
|
+
}
|
|
71
|
+
|
|
43
72
|
setPublickey(val) {
|
|
44
73
|
if (!val) this.throwHelp(`DNSKEY: publickey is required`)
|
|
45
74
|
|
|
@@ -66,12 +95,10 @@ export default class DNSKEY extends RR {
|
|
|
66
95
|
|
|
67
96
|
fromBind(opts) {
|
|
68
97
|
// test.example.com 3600 IN DNSKEY Flags Protocol Algorithm PublicKey
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
)
|
|
98
|
+
const regex = /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+\s*(.*?)\s*$/
|
|
99
|
+
const match = opts.bindline.match(regex)
|
|
72
100
|
if (!match) this.throwHelp(`unable to parse DNSKEY: ${opts.bindline}`)
|
|
73
|
-
const [owner, ttl, c, type, flags, protocol, algorithm, publickey] =
|
|
74
|
-
match.slice(1)
|
|
101
|
+
const [owner, ttl, c, type, flags, protocol, algorithm, publickey] = match.slice(1)
|
|
75
102
|
|
|
76
103
|
return new DNSKEY({
|
|
77
104
|
owner,
|
package/rr/ds.js
CHANGED
|
@@ -17,13 +17,23 @@ export default class DS extends RR {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
setAlgorithm(val) {
|
|
20
|
-
|
|
21
|
-
if (![1, 2, 3, 4, 5, 253, 254].includes(val))
|
|
22
|
-
this.throwHelp(`DS: algorithm invalid`)
|
|
20
|
+
if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`DS: algorithm invalid`)
|
|
23
21
|
|
|
24
22
|
this.set('algorithm', val)
|
|
25
23
|
}
|
|
26
24
|
|
|
25
|
+
getAlgorithmOptions() {
|
|
26
|
+
return new Map([
|
|
27
|
+
[1, 'RSA/MD5'],
|
|
28
|
+
[2, 'DH'],
|
|
29
|
+
[3, 'DSA/SHA-1'],
|
|
30
|
+
[4, 'EC'],
|
|
31
|
+
[5, 'RSA/SHA-1'],
|
|
32
|
+
[253, ''],
|
|
33
|
+
[254, ''],
|
|
34
|
+
])
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
setDigestType(val) {
|
|
28
38
|
if (![1, 2].includes(val)) this.throwHelp(`DS: digest type invalid`)
|
|
29
39
|
|
|
@@ -56,8 +66,7 @@ export default class DS extends RR {
|
|
|
56
66
|
|
|
57
67
|
fromBind(opts) {
|
|
58
68
|
// test.example.com 3600 IN DS Key Tag Algorithm, Digest Type, Digest
|
|
59
|
-
const [owner, ttl, c, type, keytag, algorithm, digesttype] =
|
|
60
|
-
opts.bindline.split(/\s+/)
|
|
69
|
+
const [owner, ttl, c, type, keytag, algorithm, digesttype] = opts.bindline.split(/\s+/)
|
|
61
70
|
return new DS({
|
|
62
71
|
owner,
|
|
63
72
|
ttl: parseInt(ttl, 10),
|
package/rr/hinfo.js
CHANGED
|
@@ -41,11 +41,8 @@ export default class HINFO extends RR {
|
|
|
41
41
|
/****** IMPORTERS *******/
|
|
42
42
|
fromBind(opts) {
|
|
43
43
|
// test.example.com 3600 IN HINFO DEC-2060 TOPS20
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
.match(
|
|
47
|
-
/^([\S]+)\s+([0-9]{1,10})\s+(IN)\s+(HINFO)\s+("[^"]+"|[\S]+)\s+("[^"]+"|[\S]+)/i,
|
|
48
|
-
)
|
|
44
|
+
const regex = /^([\S]+)\s+([0-9]{1,10})\s+(IN)\s+(HINFO)\s+("[^"]+"|[\S]+)\s+("[^"]+"|[\S]+)/i
|
|
45
|
+
const match = opts.bindline.trim().match(regex)
|
|
49
46
|
if (!match) this.throwHelp(`unable to parse HINFO: ${opts.bindline}`)
|
|
50
47
|
const [owner, ttl, c, type, cpu, os] = match.slice(1)
|
|
51
48
|
|
|
@@ -78,10 +75,7 @@ export default class HINFO extends RR {
|
|
|
78
75
|
/****** EXPORTERS *******/
|
|
79
76
|
toTinydns() {
|
|
80
77
|
return this.getTinydnsGeneric(
|
|
81
|
-
[
|
|
82
|
-
TINYDNS.packString(this.get('cpu')),
|
|
83
|
-
TINYDNS.packString(this.get('os')),
|
|
84
|
-
].join(''),
|
|
78
|
+
[TINYDNS.packString(this.get('cpu')), TINYDNS.packString(this.get('os'))].join(''),
|
|
85
79
|
)
|
|
86
80
|
}
|
|
87
81
|
}
|
package/rr/hip.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import RR from '../rr.js'
|
|
2
|
+
|
|
3
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
|
+
|
|
5
|
+
export default class HIP extends RR {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
super(opts)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/****** Resource record specific setters *******/
|
|
11
|
+
setPkAlgorithm(val) {
|
|
12
|
+
if (val === undefined) this.throwHelp('HIP: pk algorithm is required')
|
|
13
|
+
this.is8bitInt('HIP', 'pk algorithm', val)
|
|
14
|
+
this.set('pk algorithm', val)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setHit(val) {
|
|
18
|
+
if (!val) this.throwHelp('HIP: hit is required')
|
|
19
|
+
this.set('hit', val)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setPublicKey(val) {
|
|
23
|
+
if (!val) this.throwHelp('HIP: public key is required')
|
|
24
|
+
this.set('public key', val)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setRendezvousServers(val) {
|
|
28
|
+
this.set('rendezvous servers', val ?? '')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getDescription() {
|
|
32
|
+
return 'Host Identity Protocol'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getRdataFields(arg) {
|
|
36
|
+
return ['pk algorithm', 'hit', 'public key', 'rendezvous servers']
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getRFCs() {
|
|
40
|
+
return [8005]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getTypeId() {
|
|
44
|
+
return 55
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getCanonical() {
|
|
48
|
+
return {
|
|
49
|
+
owner: 'example.com.',
|
|
50
|
+
ttl: 3600,
|
|
51
|
+
class: 'IN',
|
|
52
|
+
type: 'HIP',
|
|
53
|
+
'pk algorithm': 2,
|
|
54
|
+
hit: '200100107B1A74DF365639CC39F1D578',
|
|
55
|
+
'public key':
|
|
56
|
+
'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',
|
|
57
|
+
'rendezvous servers': '',
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/****** IMPORTERS *******/
|
|
62
|
+
fromBind(opts) {
|
|
63
|
+
// owner ttl IN HIP pk-algorithm HIT public-key [rendezvous-server...]
|
|
64
|
+
const parts = opts.bindline.split(/\s+/)
|
|
65
|
+
const [owner, ttl, c, type, pkAlgorithm, hit, publicKey] = parts
|
|
66
|
+
return new HIP({
|
|
67
|
+
owner,
|
|
68
|
+
ttl: parseInt(ttl, 10),
|
|
69
|
+
class: c,
|
|
70
|
+
type,
|
|
71
|
+
'pk algorithm': parseInt(pkAlgorithm, 10),
|
|
72
|
+
hit,
|
|
73
|
+
'public key': publicKey,
|
|
74
|
+
'rendezvous servers': parts.slice(7).join(' ').trim(),
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/****** EXPORTERS *******/
|
|
79
|
+
toBind(zone_opts) {
|
|
80
|
+
const rs = this.get('rendezvous servers')
|
|
81
|
+
const rsPart = rs ? `\t${rs}` : ''
|
|
82
|
+
return `${this.getPrefix(zone_opts)}\t${this.get('pk algorithm')}\t${this.get('hit')}\t${this.get('public key')}${rsPart}\n`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
toTinydns() {
|
|
86
|
+
const hitBytes = Buffer.from(this.get('hit'), 'hex')
|
|
87
|
+
const pkBytes = Buffer.from(this.get('public key'), 'base64')
|
|
88
|
+
const rs = this.get('rendezvous servers')
|
|
89
|
+
|
|
90
|
+
let rdata = ''
|
|
91
|
+
rdata += TINYDNS.UInt8toOctal(hitBytes.length)
|
|
92
|
+
rdata += TINYDNS.UInt8toOctal(this.get('pk algorithm'))
|
|
93
|
+
rdata += TINYDNS.UInt16toOctal(pkBytes.length)
|
|
94
|
+
for (const b of hitBytes) rdata += TINYDNS.UInt8toOctal(b)
|
|
95
|
+
for (const b of pkBytes) rdata += TINYDNS.UInt8toOctal(b)
|
|
96
|
+
if (rs) {
|
|
97
|
+
for (const name of rs.split(/\s+/)) rdata += TINYDNS.packDomainName(name)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return this.getTinydnsGeneric(rdata)
|
|
101
|
+
}
|
|
102
|
+
}
|
package/rr/https.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 HTTPS extends RR {
|
|
4
6
|
constructor(opts) {
|
|
5
7
|
super(opts)
|
|
@@ -59,4 +61,14 @@ export default class HTTPS extends RR {
|
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
/****** EXPORTERS *******/
|
|
64
|
+
|
|
65
|
+
toTinydns() {
|
|
66
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
67
|
+
|
|
68
|
+
return this.getTinydnsGeneric(
|
|
69
|
+
TINYDNS.UInt16toOctal(this.get('priority')) +
|
|
70
|
+
TINYDNS.packDomainName(this.get('target name')) +
|
|
71
|
+
TINYDNS.escapeOctal(dataRe, this.get('params')),
|
|
72
|
+
)
|
|
73
|
+
}
|
|
62
74
|
}
|
package/rr/ipseckey.js
CHANGED
|
@@ -16,23 +16,37 @@ export default class IPSECKEY extends RR {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
setGatewayType(val) {
|
|
19
|
-
|
|
20
|
-
if (![0, 1, 2, 3].includes(val))
|
|
21
|
-
this.throwHelp(`IPSECKEY: Gateway Type is invalid`)
|
|
19
|
+
if (!this.getGatewayTypeOptions().has(val)) this.throwHelp(`IPSECKEY: Gateway Type is invalid`)
|
|
22
20
|
|
|
23
21
|
this.set('gateway type', val)
|
|
24
22
|
}
|
|
25
23
|
|
|
24
|
+
getGatewayTypeOptions() {
|
|
25
|
+
return new Map([
|
|
26
|
+
[0, 'none'],
|
|
27
|
+
[1, '4-byte IPv4'],
|
|
28
|
+
[2, '16-byte IPv6'],
|
|
29
|
+
[3, 'wire encoded domain name'],
|
|
30
|
+
])
|
|
31
|
+
}
|
|
32
|
+
|
|
26
33
|
setAlgorithm(val) {
|
|
27
|
-
|
|
28
|
-
if (![1, 2].includes(val)) this.throwHelp(`IPSECKEY: Algorithm invalid`)
|
|
34
|
+
if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`IPSECKEY: Algorithm invalid`)
|
|
29
35
|
|
|
30
36
|
this.set('algorithm', val)
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
getAlgorithmOptions() {
|
|
40
|
+
return new Map([
|
|
41
|
+
[1, 'DSA'],
|
|
42
|
+
[2, 'RSA'],
|
|
43
|
+
])
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
setGateway(val) {
|
|
34
|
-
const
|
|
35
|
-
|
|
47
|
+
const type = this.get('gateway type')
|
|
48
|
+
const gwErr = new Error(`IPSECKEY: gateway invalid (${val}) for type ${type}`)
|
|
49
|
+
switch (type) {
|
|
36
50
|
case 0:
|
|
37
51
|
if (val !== '.') throw gwErr
|
|
38
52
|
break
|
|
@@ -86,8 +100,7 @@ export default class IPSECKEY extends RR {
|
|
|
86
100
|
/****** IMPORTERS *******/
|
|
87
101
|
fromBind(opts) {
|
|
88
102
|
// FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey
|
|
89
|
-
const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] =
|
|
90
|
-
opts.bindline.split(/\s+/)
|
|
103
|
+
const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] = opts.bindline.split(/\s+/)
|
|
91
104
|
return new IPSECKEY({
|
|
92
105
|
owner,
|
|
93
106
|
ttl: parseInt(ttl, 10),
|
package/rr/key.js
CHANGED
|
@@ -22,13 +22,24 @@ export default class KEY extends RR {
|
|
|
22
22
|
|
|
23
23
|
setAlgorithm(val) {
|
|
24
24
|
// 1 octet
|
|
25
|
-
|
|
26
|
-
if (!
|
|
27
|
-
this.throwHelp(`KEY: algorithm invalid`)
|
|
25
|
+
|
|
26
|
+
if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`KEY: algorithm invalid`)
|
|
28
27
|
|
|
29
28
|
this.set('algorithm', val)
|
|
30
29
|
}
|
|
31
30
|
|
|
31
|
+
getAlgorithmOptions() {
|
|
32
|
+
return new Map([
|
|
33
|
+
[1, 'RSA/MD5'],
|
|
34
|
+
[2, 'DH'],
|
|
35
|
+
[3, 'DSA/SHA-1'],
|
|
36
|
+
[4, 'EC'],
|
|
37
|
+
[5, 'RSA/SHA-1'],
|
|
38
|
+
[253, ''],
|
|
39
|
+
[254, ''],
|
|
40
|
+
])
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
setPublickey(val) {
|
|
33
44
|
if (!val) this.throwHelp(`KEY: publickey is required`)
|
|
34
45
|
|
|
@@ -55,8 +66,7 @@ export default class KEY extends RR {
|
|
|
55
66
|
|
|
56
67
|
fromBind(opts) {
|
|
57
68
|
// test.example.com 3600 IN KEY Flags Protocol Algorithm PublicKey
|
|
58
|
-
const [owner, ttl, c, type, flags, protocol, algorithm] =
|
|
59
|
-
opts.bindline.split(/\s+/)
|
|
69
|
+
const [owner, ttl, c, type, flags, protocol, algorithm] = opts.bindline.split(/\s+/)
|
|
60
70
|
return new KEY({
|
|
61
71
|
owner,
|
|
62
72
|
ttl: parseInt(ttl, 10),
|
package/rr/kx.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import RR from '../rr.js'
|
|
2
|
+
|
|
3
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
|
+
|
|
5
|
+
export default class KX extends RR {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
super(opts)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/****** Resource record specific setters *******/
|
|
11
|
+
setPreference(val) {
|
|
12
|
+
if (val === undefined) this.throwHelp('KX: preference is required')
|
|
13
|
+
this.is16bitInt('KX', 'preference', val)
|
|
14
|
+
this.set('preference', val)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setExchanger(val) {
|
|
18
|
+
if (!val) this.throwHelp('KX: exchanger is required')
|
|
19
|
+
|
|
20
|
+
this.isFullyQualified('KX', 'exchanger', val)
|
|
21
|
+
this.isValidHostname('KX', 'exchanger', val)
|
|
22
|
+
|
|
23
|
+
this.set('exchanger', val.toLowerCase())
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getDescription() {
|
|
27
|
+
return 'Key Exchanger'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getRdataFields(arg) {
|
|
31
|
+
return ['preference', 'exchanger']
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getRFCs() {
|
|
35
|
+
return [2230]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getTypeId() {
|
|
39
|
+
return 36
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getCanonical() {
|
|
43
|
+
return {
|
|
44
|
+
owner: 'example.com.',
|
|
45
|
+
ttl: 3600,
|
|
46
|
+
class: 'IN',
|
|
47
|
+
type: 'KX',
|
|
48
|
+
preference: 10,
|
|
49
|
+
exchanger: 'kx.example.com.',
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/****** IMPORTERS *******/
|
|
54
|
+
fromBind(opts) {
|
|
55
|
+
// test.example.com 3600 IN KX preference exchanger
|
|
56
|
+
const [owner, ttl, c, type, preference, exchanger] = opts.bindline.split(/\s+/)
|
|
57
|
+
return new KX({
|
|
58
|
+
owner,
|
|
59
|
+
ttl: parseInt(ttl, 10),
|
|
60
|
+
class: c,
|
|
61
|
+
type,
|
|
62
|
+
preference: parseInt(preference, 10),
|
|
63
|
+
exchanger,
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/****** EXPORTERS *******/
|
|
68
|
+
toBind(zone_opts) {
|
|
69
|
+
return `${this.getPrefix(zone_opts)}\t${this.get('preference')}\t${this.getFQDN('exchanger', zone_opts)}\n`
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
toTinydns() {
|
|
73
|
+
return this.getTinydnsGeneric(
|
|
74
|
+
TINYDNS.UInt16toOctal(this.get('preference')) + TINYDNS.packDomainName(this.get('exchanger')),
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
}
|
package/rr/loc.js
CHANGED
|
@@ -53,8 +53,7 @@ export default class LOC extends RR {
|
|
|
53
53
|
const dms = '(\\d+)\\s+(?:(\\d+)\\s+)?(?:([\\d.]+)\\s+)?'
|
|
54
54
|
|
|
55
55
|
// alt["m"] [siz["m"] [hp["m"] [vp["m"]]]]
|
|
56
|
-
const alt =
|
|
57
|
-
'(-?[\\d.]+)m?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?'
|
|
56
|
+
const alt = '(-?[\\d.]+)m?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?'
|
|
58
57
|
|
|
59
58
|
// put them all together
|
|
60
59
|
const locRe = new RegExp(`^${dms}(N|S)\\s+${dms}(E|W)\\s+${alt}`, 'i')
|
|
@@ -96,21 +95,11 @@ export default class LOC extends RR {
|
|
|
96
95
|
version: TINYDNS.octalToUInt8(rdata.substring(0, 4)),
|
|
97
96
|
size: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(4, 8))),
|
|
98
97
|
precision: {
|
|
99
|
-
horizontal: this.fromExponent(
|
|
100
|
-
|
|
101
|
-
),
|
|
102
|
-
vertical: this.fromExponent(
|
|
103
|
-
TINYDNS.octalToUInt8(rdata.substring(12, 16)),
|
|
104
|
-
),
|
|
98
|
+
horizontal: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(8, 12))),
|
|
99
|
+
vertical: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(12, 16))),
|
|
105
100
|
},
|
|
106
|
-
latitude: this.arcSecToDMS(
|
|
107
|
-
|
|
108
|
-
'lat',
|
|
109
|
-
),
|
|
110
|
-
longitude: this.arcSecToDMS(
|
|
111
|
-
TINYDNS.octalToUInt32(rdata.substring(32, 48)),
|
|
112
|
-
'lon',
|
|
113
|
-
),
|
|
101
|
+
latitude: this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.substring(16, 32)), 'lat'),
|
|
102
|
+
longitude: this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.substring(32, 48)), 'lon'),
|
|
114
103
|
altitude: TINYDNS.octalToUInt32(rdata.substring(48, 64)) - REF.ALTITUDE,
|
|
115
104
|
}
|
|
116
105
|
|
|
@@ -137,10 +126,7 @@ export default class LOC extends RR {
|
|
|
137
126
|
}
|
|
138
127
|
|
|
139
128
|
dmsToArcSec(obj) {
|
|
140
|
-
let retval =
|
|
141
|
-
obj.degrees * CONV.deg +
|
|
142
|
-
(obj.minutes || 0) * CONV.min +
|
|
143
|
-
(obj.seconds || 0) * CONV.sec
|
|
129
|
+
let retval = obj.degrees * CONV.deg + (obj.minutes || 0) * CONV.min + (obj.seconds || 0) * CONV.sec
|
|
144
130
|
switch (obj.hemisphere.toUpperCase()) {
|
|
145
131
|
case 'W':
|
|
146
132
|
case 'S':
|
package/rr/mx.js
CHANGED
|
@@ -16,8 +16,7 @@ export default class MX extends RR {
|
|
|
16
16
|
setExchange(val) {
|
|
17
17
|
if (!val) this.throwHelp('MX: exchange is required')
|
|
18
18
|
|
|
19
|
-
if (this.isIPv4(val) || this.isIPv6(val))
|
|
20
|
-
this.throwHelp(`MX: exchange must be a FQDN`)
|
|
19
|
+
if (this.isIPv4(val) || this.isIPv6(val)) this.throwHelp(`MX: exchange must be a FQDN`)
|
|
21
20
|
|
|
22
21
|
this.isFullyQualified('MX', 'exchange', val)
|
|
23
22
|
this.isValidHostname('MX', 'exchange', val)
|
|
@@ -57,9 +56,7 @@ export default class MX extends RR {
|
|
|
57
56
|
fromTinydns(opts) {
|
|
58
57
|
// @fqdn:ip:x:dist:ttl:timestamp:lo
|
|
59
58
|
// eslint-disable-next-line no-unused-vars
|
|
60
|
-
const [owner, ip, x, preference, ttl, ts, loc] = opts.tinyline
|
|
61
|
-
.substring(1)
|
|
62
|
-
.split(':')
|
|
59
|
+
const [owner, ip, x, preference, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
|
|
63
60
|
|
|
64
61
|
return new MX({
|
|
65
62
|
type: 'MX',
|
|
@@ -74,8 +71,7 @@ export default class MX extends RR {
|
|
|
74
71
|
|
|
75
72
|
fromBind(opts) {
|
|
76
73
|
// test.example.com 3600 IN MX preference exchange
|
|
77
|
-
const [owner, ttl, c, type, preference, exchange] =
|
|
78
|
-
opts.bindline.split(/\s+/)
|
|
74
|
+
const [owner, ttl, c, type, preference, exchange] = opts.bindline.split(/\s+/)
|
|
79
75
|
|
|
80
76
|
return new MX({
|
|
81
77
|
owner,
|
package/rr/naptr.js
CHANGED
|
@@ -40,12 +40,15 @@ export default class NAPTR extends RR {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
setFlags(val) {
|
|
43
|
-
if (!
|
|
44
|
-
this.throwHelp(`NAPTR flags are invalid`)
|
|
43
|
+
if (!this.getFlagsOptions().has(val.toUpperCase())) this.throwHelp(`NAPTR flags are invalid`)
|
|
45
44
|
|
|
46
45
|
this.set('flags', val.toUpperCase())
|
|
47
46
|
}
|
|
48
47
|
|
|
48
|
+
getFlagsOptions() {
|
|
49
|
+
return new Map([[''], ['S'], ['A'], ['U'], ['P']])
|
|
50
|
+
}
|
|
51
|
+
|
|
49
52
|
setService(val) {
|
|
50
53
|
this.set('service', val)
|
|
51
54
|
}
|
package/rr/ns.js
CHANGED
|
@@ -37,16 +37,12 @@ export default class NS extends RR {
|
|
|
37
37
|
fromTinydns(opts) {
|
|
38
38
|
// &fqdn:ip:x:ttl:timestamp:lo
|
|
39
39
|
// eslint-disable-next-line no-unused-vars
|
|
40
|
-
const [fqdn, ip, dname, ttl, ts, loc] = opts.tinyline
|
|
41
|
-
.substring(1)
|
|
42
|
-
.split(':')
|
|
40
|
+
const [fqdn, ip, dname, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
|
|
43
41
|
|
|
44
42
|
return new NS({
|
|
45
43
|
type: 'NS',
|
|
46
44
|
owner: this.fullyQualify(fqdn),
|
|
47
|
-
dname: this.fullyQualify(
|
|
48
|
-
/\./.test(dname) ? dname : `${dname}.ns.${fqdn}`,
|
|
49
|
-
),
|
|
45
|
+
dname: this.fullyQualify(/\./.test(dname) ? dname : `${dname}.ns.${fqdn}`),
|
|
50
46
|
ttl: parseInt(ttl, 10),
|
|
51
47
|
timestamp: ts,
|
|
52
48
|
location: loc !== '' && loc !== '\n' ? loc : '',
|
package/rr/nsec.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 NSEC extends RR {
|
|
4
6
|
constructor(opts) {
|
|
5
7
|
super(opts)
|
|
@@ -50,16 +52,20 @@ export default class NSEC extends RR {
|
|
|
50
52
|
class: c,
|
|
51
53
|
type: type,
|
|
52
54
|
'next domain': next,
|
|
53
|
-
'type bit maps': opts.bindline
|
|
54
|
-
.split(/\s+/)
|
|
55
|
-
.slice(5)
|
|
56
|
-
.filter(removeParens)
|
|
57
|
-
.join(' ')
|
|
58
|
-
.trim(),
|
|
55
|
+
'type bit maps': opts.bindline.split(/\s+/).slice(5).filter(removeParens).join(' ').trim(),
|
|
59
56
|
})
|
|
60
57
|
}
|
|
61
58
|
|
|
62
59
|
/****** EXPORTERS *******/
|
|
60
|
+
|
|
61
|
+
toTinydns() {
|
|
62
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
63
|
+
|
|
64
|
+
return this.getTinydnsGeneric(
|
|
65
|
+
TINYDNS.packDomainName(this.get('next domain')) +
|
|
66
|
+
TINYDNS.escapeOctal(dataRe, this.get('type bit maps')),
|
|
67
|
+
)
|
|
68
|
+
}
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
const removeParens = (a) => !['(', ')'].includes(a)
|
package/rr/nsec3.js
CHANGED
|
@@ -65,14 +65,7 @@ export default class NSEC3 extends RR {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
getRdataFields(arg) {
|
|
68
|
-
return [
|
|
69
|
-
'hash algorithm',
|
|
70
|
-
'flags',
|
|
71
|
-
'iterations',
|
|
72
|
-
'salt',
|
|
73
|
-
'next hashed owner name',
|
|
74
|
-
'type bit maps',
|
|
75
|
-
]
|
|
68
|
+
return ['hash algorithm', 'flags', 'iterations', 'salt', 'next hashed owner name', 'type bit maps']
|
|
76
69
|
}
|
|
77
70
|
|
|
78
71
|
getRFCs() {
|
|
@@ -87,8 +80,7 @@ export default class NSEC3 extends RR {
|
|
|
87
80
|
|
|
88
81
|
fromBind(opts) {
|
|
89
82
|
// test.example.com. 3600 IN NSEC3 1 1 12 aabbccdd (2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG)
|
|
90
|
-
const [owner, ttl, c, type, ha, flags, iterations, salt] =
|
|
91
|
-
opts.bindline.split(/\s+/)
|
|
83
|
+
const [owner, ttl, c, type, ha, flags, iterations, salt] = opts.bindline.split(/\s+/)
|
|
92
84
|
const rdata = opts.bindline.split(/\(|\)/)[1]
|
|
93
85
|
|
|
94
86
|
return new NSEC3({
|
package/rr/nxt.js
CHANGED
|
@@ -50,12 +50,7 @@ export default class NXT extends RR {
|
|
|
50
50
|
class: c,
|
|
51
51
|
type: type,
|
|
52
52
|
'next domain': next,
|
|
53
|
-
'type bit map': opts.bindline
|
|
54
|
-
.split(/\s+/)
|
|
55
|
-
.slice(5)
|
|
56
|
-
.filter(removeParens)
|
|
57
|
-
.join(' ')
|
|
58
|
-
.trim(),
|
|
53
|
+
'type bit map': opts.bindline.split(/\s+/).slice(5).filter(removeParens).join(' ').trim(),
|
|
59
54
|
})
|
|
60
55
|
}
|
|
61
56
|
|
package/rr/openpgpkey.js
CHANGED
|
@@ -29,10 +29,9 @@ export default class OPENPGPKEY extends RR {
|
|
|
29
29
|
/****** IMPORTERS *******/
|
|
30
30
|
fromBind(obj) {
|
|
31
31
|
// test.example.com 3600 IN OPENPGPKEY <base64 public key>
|
|
32
|
+
const regex = /^([\S]+)\s+(\d{1,10})\s+(IN)\s+(OPENPGPKEY)\s+([\W\w]*)$/
|
|
32
33
|
// eslint-disable-next-line no-unused-vars
|
|
33
|
-
const [ignore, owner, ttl, c, type, publickey] = obj.bindline
|
|
34
|
-
.trim()
|
|
35
|
-
.match(/^([\S]+)\s+(\d{1,10})\s+(IN)\s+(OPENPGPKEY)\s+([\W\w]*)$/)
|
|
34
|
+
const [ignore, owner, ttl, c, type, publickey] = obj.bindline.trim().match(regex)
|
|
36
35
|
|
|
37
36
|
return new OPENPGPKEY({
|
|
38
37
|
owner,
|