@nictool/dns-resource-record 1.3.1 → 1.4.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 +12 -0
- package/lib/tinydns.js +35 -14
- package/package.json +8 -8
- package/rr/cert.js +35 -0
- package/rr/https.js +21 -0
- package/rr/key.js +35 -0
- package/rr/naptr.js +1 -1
- package/rr/nsec.js +16 -0
- package/rr/nsec3.js +23 -11
- package/rr/nsec3param.js +45 -8
- package/rr/nxt.js +28 -0
- package/rr/openpgpkey.js +18 -0
- package/rr/sig.js +10 -0
- package/rr/smimea.js +17 -0
- package/rr/svcb.js +23 -0
- package/rr/tlsa.js +1 -1
- package/rr/uri.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ Notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
#### Unreleased
|
|
6
6
|
|
|
7
|
+
### [1.4.0] - 2026-03-21
|
|
8
|
+
|
|
9
|
+
#### Changed
|
|
10
|
+
|
|
11
|
+
- feat(toBind): added to nsec3param, rrsig
|
|
12
|
+
- feat(toTinydns): added to key, nsec3param, nxt, openpgpkey
|
|
13
|
+
- feat(fromTinydns): added to cert, https, key, nsec, nsec3param, nxt, openpgpkey, smimea, svcb
|
|
14
|
+
- fix(naptr): fixed flags calc in fromTinydns
|
|
15
|
+
- fix(tinydns): more robust unpackDomainName
|
|
16
|
+
- test: switch test runner to node --test
|
|
17
|
+
|
|
7
18
|
### [1.3.1] - 2026-03-13
|
|
8
19
|
|
|
9
20
|
- ci: update workflow triggers
|
|
@@ -338,3 +349,4 @@ Notable changes to this project are documented in this file.
|
|
|
338
349
|
[1.2.4]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.4
|
|
339
350
|
[1.3.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.3.0
|
|
340
351
|
[1.3.1]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.3.1
|
|
352
|
+
[1.4.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.4.0
|
package/lib/tinydns.js
CHANGED
|
@@ -27,6 +27,10 @@ export function escapeOctal(re, str) {
|
|
|
27
27
|
return escaped
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export function unescapeOctal(str) {
|
|
31
|
+
return this.octalToChar(str)
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
export function octalToChar(str) {
|
|
31
35
|
// relace instances of \NNN with ASCII
|
|
32
36
|
return str.replace(octalRe, (o) => String.fromCharCode(parseInt(o.substring(1), 8)))
|
|
@@ -108,22 +112,39 @@ export function packDomainName(fqdn) {
|
|
|
108
112
|
return packed
|
|
109
113
|
}
|
|
110
114
|
|
|
111
|
-
export function unpackDomainName(
|
|
112
|
-
fqdn = Buffer.from(octalToChar(fqdn.toString()))
|
|
113
|
-
|
|
114
|
-
const labels = []
|
|
115
|
+
export function unpackDomainName(escaped) {
|
|
115
116
|
let pos = 0
|
|
116
|
-
let
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
let binaryLen = 0
|
|
118
|
+
const labels = []
|
|
119
|
+
|
|
120
|
+
// consume the next logical "byte" (char or octal escape)
|
|
121
|
+
const getNextByte = () => {
|
|
122
|
+
if (pos >= escaped.length) return null
|
|
123
|
+
|
|
124
|
+
let value
|
|
125
|
+
if (escaped[pos] === '\\') {
|
|
126
|
+
value = parseInt(escaped.slice(pos + 1, pos + 4), 8)
|
|
127
|
+
pos += 4
|
|
128
|
+
} else {
|
|
129
|
+
value = escaped.charCodeAt(pos++)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
binaryLen++
|
|
133
|
+
return value
|
|
122
134
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
135
|
+
|
|
136
|
+
let lengthByte
|
|
137
|
+
while ((lengthByte = getNextByte()) && lengthByte !== 0) {
|
|
138
|
+
let label = ''
|
|
139
|
+
for (let i = 0; i < lengthByte; i++) {
|
|
140
|
+
const char = getNextByte()
|
|
141
|
+
if (char === null) break
|
|
142
|
+
label += String.fromCharCode(char)
|
|
143
|
+
}
|
|
144
|
+
labels.push(label)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return [`${labels.join('.')}.`, pos, binaryLen]
|
|
127
148
|
}
|
|
128
149
|
|
|
129
150
|
export function packHex(str) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nictool/dns-resource-record",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "DNS Resource Records",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
"lint:fix": "npm run lint -- --fix",
|
|
18
18
|
"prettier": "npx prettier --ignore-path .gitignore --check .",
|
|
19
19
|
"prettier:fix": "npx prettier --ignore-path .gitignore --write .",
|
|
20
|
-
"test": "
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"versions:fix": "npx
|
|
20
|
+
"test": "node --test test/*.js",
|
|
21
|
+
"test:coverage": "npx c8 --reporter=text --reporter=text-summary npm test",
|
|
22
|
+
"versions": "npx npm-dep-mgr check",
|
|
23
|
+
"versions:fix": "npx npm-dep-mgr update",
|
|
24
|
+
"watch": "node --test --watch test/*.js"
|
|
24
25
|
},
|
|
25
26
|
"repository": {
|
|
26
27
|
"type": "git",
|
|
@@ -47,9 +48,8 @@
|
|
|
47
48
|
"homepage": "https://github.com/NicTool/dns-resource-record#readme",
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@eslint/js": "^10.0.1",
|
|
50
|
-
"eslint": "^10.0
|
|
51
|
-
"globals": "^17.4.0"
|
|
52
|
-
"mocha": "^11.7.5"
|
|
51
|
+
"eslint": "^10.1.0",
|
|
52
|
+
"globals": "^17.4.0"
|
|
53
53
|
},
|
|
54
54
|
"prettier": {
|
|
55
55
|
"printWidth": 110,
|
package/rr/cert.js
CHANGED
|
@@ -75,6 +75,41 @@ export default class CERT extends RR {
|
|
|
75
75
|
|
|
76
76
|
/****** IMPORTERS *******/
|
|
77
77
|
|
|
78
|
+
fromTinydns(opts) {
|
|
79
|
+
const [owner, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
|
|
80
|
+
if (n != 37) this.throwHelp('CERT fromTinydns, invalid n')
|
|
81
|
+
|
|
82
|
+
const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
83
|
+
const typeNum = bytes.readUInt16BE(0)
|
|
84
|
+
let certType = typeNum
|
|
85
|
+
|
|
86
|
+
const types = {
|
|
87
|
+
1: 'PKIX',
|
|
88
|
+
2: 'SPKI',
|
|
89
|
+
3: 'PGP',
|
|
90
|
+
4: 'IPKIX',
|
|
91
|
+
5: 'ISPKI',
|
|
92
|
+
6: 'IPGP',
|
|
93
|
+
7: 'ACPKIX',
|
|
94
|
+
8: 'IACPKIX',
|
|
95
|
+
253: 'URI',
|
|
96
|
+
254: 'OID',
|
|
97
|
+
}
|
|
98
|
+
if (types[typeNum]) certType = types[typeNum]
|
|
99
|
+
|
|
100
|
+
return new CERT({
|
|
101
|
+
owner: this.fullyQualify(owner),
|
|
102
|
+
ttl: parseInt(ttl, 10),
|
|
103
|
+
type: 'CERT',
|
|
104
|
+
'cert type': certType,
|
|
105
|
+
'key tag': bytes.readUInt16BE(2),
|
|
106
|
+
algorithm: bytes.readUInt8(4),
|
|
107
|
+
certificate: bytes.slice(5).toString(),
|
|
108
|
+
timestamp: ts,
|
|
109
|
+
location: loc !== '' && loc !== '\n' ? loc : '',
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
78
113
|
fromBind(opts) {
|
|
79
114
|
// test.example.com 3600 IN CERT certtype, keytag, algo, cert
|
|
80
115
|
const [owner, ttl, c, type, certtype, keytag, algo, certificate] = opts.bindline.split(/\s+/)
|
package/rr/https.js
CHANGED
|
@@ -60,6 +60,27 @@ export default class HTTPS extends RR {
|
|
|
60
60
|
})
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
fromTinydns({ rd, owner, ttl }) {
|
|
64
|
+
if (rd.length < 6) {
|
|
65
|
+
this.throwHelp(`HTTPS: RDATA too short: ${rd}`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const priority = TINYDNS.octalToUInt16(rd.substring(0, 6))
|
|
69
|
+
const remaining = rd.slice(6)
|
|
70
|
+
|
|
71
|
+
const [targetName, consumed] = TINYDNS.unpackDomainName(remaining)
|
|
72
|
+
const params = TINYDNS.escapeOctal(remaining.slice(consumed))
|
|
73
|
+
|
|
74
|
+
return new HTTPS({
|
|
75
|
+
owner: this.fullyQualify(owner),
|
|
76
|
+
ttl: parseInt(ttl, 10),
|
|
77
|
+
type: 'HTTPS',
|
|
78
|
+
priority,
|
|
79
|
+
'target name': targetName,
|
|
80
|
+
params,
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
63
84
|
/****** EXPORTERS *******/
|
|
64
85
|
|
|
65
86
|
toTinydns() {
|
package/rr/key.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
2
3
|
|
|
3
4
|
export default class KEY extends RR {
|
|
4
5
|
constructor(opts) {
|
|
@@ -79,5 +80,39 @@ export default class KEY extends RR {
|
|
|
79
80
|
})
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
fromTinydns(opts) {
|
|
84
|
+
const rd = opts.rd
|
|
85
|
+
|
|
86
|
+
// RDATA format: Flags (6 octal chars) + Protocol (3 octal chars) + Algorithm (3 octal chars) + Public Key (escaped data)
|
|
87
|
+
if (rd.length < 12) {
|
|
88
|
+
this.throwHelp(`KEY: RDATA too short: ${rd}`)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const flags = TINYDNS.octalToUInt16(rd.substring(0, 6))
|
|
92
|
+
const protocol = TINYDNS.octalToUInt8(rd.substring(6, 9))
|
|
93
|
+
const algorithm = TINYDNS.octalToUInt8(rd.substring(9, 12))
|
|
94
|
+
const publicKeyData = TINYDNS.unescapeOctal(rd.substring(12))
|
|
95
|
+
|
|
96
|
+
return new KEY({
|
|
97
|
+
owner: this.fullyQualify(opts.owner),
|
|
98
|
+
ttl: parseInt(opts.ttl, 10),
|
|
99
|
+
type: 'KEY',
|
|
100
|
+
flags: flags,
|
|
101
|
+
protocol: protocol,
|
|
102
|
+
algorithm: algorithm,
|
|
103
|
+
publickey: publicKeyData,
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
82
107
|
/****** EXPORTERS *******/
|
|
108
|
+
toTinydns() {
|
|
109
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
110
|
+
|
|
111
|
+
return this.getTinydnsGeneric(
|
|
112
|
+
TINYDNS.UInt16toOctal(this.get('flags')) +
|
|
113
|
+
TINYDNS.UInt8toOctal(this.get('protocol')) +
|
|
114
|
+
TINYDNS.UInt8toOctal(this.get('algorithm')) +
|
|
115
|
+
TINYDNS.escapeOctal(dataRe, this.get('publickey')),
|
|
116
|
+
)
|
|
117
|
+
}
|
|
83
118
|
}
|
package/rr/naptr.js
CHANGED
|
@@ -82,7 +82,7 @@ export default class NAPTR extends RR {
|
|
|
82
82
|
let idx = 4
|
|
83
83
|
const flagsLength = binRdata.readUInt8(idx)
|
|
84
84
|
idx++
|
|
85
|
-
rec.flags = binRdata.slice(idx, flagsLength).toString()
|
|
85
|
+
rec.flags = binRdata.slice(idx, idx + flagsLength).toString()
|
|
86
86
|
idx += flagsLength
|
|
87
87
|
|
|
88
88
|
const serviceLen = binRdata.readUInt8(idx)
|
package/rr/nsec.js
CHANGED
|
@@ -43,6 +43,22 @@ export default class NSEC extends RR {
|
|
|
43
43
|
|
|
44
44
|
/****** IMPORTERS *******/
|
|
45
45
|
|
|
46
|
+
fromTinydns(opts) {
|
|
47
|
+
const [owner, _typeId, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
|
|
48
|
+
const binaryRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
49
|
+
const [nextDomain, _escapedLen, binaryLen] = TINYDNS.unpackDomainName(rdata)
|
|
50
|
+
|
|
51
|
+
return new NSEC({
|
|
52
|
+
owner: this.fullyQualify(owner),
|
|
53
|
+
ttl: parseInt(ttl, 10),
|
|
54
|
+
type: 'NSEC',
|
|
55
|
+
'next domain': nextDomain,
|
|
56
|
+
'type bit maps': binaryRdata.slice(binaryLen).toString(),
|
|
57
|
+
timestamp: ts,
|
|
58
|
+
location: loc !== '' && loc !== '\n' ? loc : '',
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
46
62
|
fromBind(opts) {
|
|
47
63
|
// test.example.com 3600 IN NSEC NextDomain TypeBitMaps
|
|
48
64
|
const [owner, ttl, c, type, next] = opts.bindline.split(/\s+/)
|
package/rr/nsec3.js
CHANGED
|
@@ -93,7 +93,7 @@ export default class NSEC3 extends RR {
|
|
|
93
93
|
iterations: parseInt(iterations, 10),
|
|
94
94
|
salt,
|
|
95
95
|
'next hashed owner name': rdata.split(/\s+/)[0],
|
|
96
|
-
'type bit maps': rdata.split(/\s+/).slice(1).join('
|
|
96
|
+
'type bit maps': rdata.split(/\s+/).slice(1).join(' '),
|
|
97
97
|
})
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -103,16 +103,27 @@ export default class NSEC3 extends RR {
|
|
|
103
103
|
|
|
104
104
|
const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
105
105
|
|
|
106
|
+
const hashAlgorithm = bytes.readUInt8(0)
|
|
107
|
+
const flags = bytes.readUInt8(1)
|
|
108
|
+
const iterations = bytes.readUInt16BE(2)
|
|
109
|
+
|
|
110
|
+
// The remaining bytes in the buffer contain:
|
|
111
|
+
// Salt Length (1 octet)
|
|
112
|
+
// Salt (variable length based on Salt Length)
|
|
113
|
+
// Next Hashed Owner Name (variable length)
|
|
114
|
+
// Type Bit Maps (variable length)
|
|
115
|
+
const { salt, nextHashedOwnerName, typeBitMaps } = TINYDNS.parseNSEC3Buffer(bytes)
|
|
116
|
+
|
|
106
117
|
return new NSEC3({
|
|
107
118
|
owner: this.fullyQualify(fqdn),
|
|
108
119
|
ttl: parseInt(ttl, 10),
|
|
109
120
|
type: 'NSEC3',
|
|
110
|
-
'hash algorithm':
|
|
111
|
-
flags:
|
|
112
|
-
iterations:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
'hash algorithm': hashAlgorithm,
|
|
122
|
+
flags: flags,
|
|
123
|
+
iterations: iterations,
|
|
124
|
+
salt: salt,
|
|
125
|
+
'next hashed owner name': nextHashedOwnerName,
|
|
126
|
+
'type bit maps': typeBitMaps,
|
|
116
127
|
timestamp: ts,
|
|
117
128
|
location: loc !== '' && loc !== '\n' ? loc : '',
|
|
118
129
|
})
|
|
@@ -121,13 +132,14 @@ export default class NSEC3 extends RR {
|
|
|
121
132
|
/****** EXPORTERS *******/
|
|
122
133
|
|
|
123
134
|
toBind(zone_opts) {
|
|
124
|
-
return `${this.getFQDN('owner', zone_opts)}
|
|
135
|
+
return `${this.getFQDN('owner', zone_opts)} ${this.get('ttl')} ${this.get('class')} NSEC3${this.getRdataFields()
|
|
125
136
|
.slice(0, 4)
|
|
126
|
-
.map((f) => '
|
|
127
|
-
.join('')}
|
|
137
|
+
.map((f) => ' ' + this.get(f))
|
|
138
|
+
.join('')} (${this.getRdataFields()
|
|
128
139
|
.slice(4)
|
|
129
140
|
.map((f) => this.get(f))
|
|
130
|
-
.join('
|
|
141
|
+
.join(' ')})
|
|
142
|
+
`
|
|
131
143
|
}
|
|
132
144
|
|
|
133
145
|
toTinydns() {
|
package/rr/nsec3param.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
2
3
|
|
|
3
4
|
export default class NSEC3PARAM extends RR {
|
|
4
5
|
constructor(opts) {
|
|
@@ -62,21 +63,57 @@ export default class NSEC3PARAM extends RR {
|
|
|
62
63
|
/****** IMPORTERS *******/
|
|
63
64
|
|
|
64
65
|
fromBind(str) {
|
|
65
|
-
// test.example.com 3600 IN NSEC3PARAM
|
|
66
|
-
|
|
66
|
+
// test.example.com 3600 IN NSEC3PARAM <hash> <flags> <iterations> <salt>
|
|
67
|
+
// Example: test.example.com. 3600 IN NSEC3PARAM 1 1 12 aabbccdd
|
|
68
|
+
const [owner, ttl, c, type, ha, flags, iterations, salt] = str.split(/\s+/)
|
|
67
69
|
return new NSEC3PARAM({
|
|
68
70
|
owner,
|
|
69
71
|
ttl: parseInt(ttl, 10),
|
|
70
72
|
class: c,
|
|
71
73
|
type: type,
|
|
72
|
-
'hash algorithm':
|
|
73
|
-
flags:
|
|
74
|
-
iterations:
|
|
75
|
-
salt:
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
'hash algorithm': parseInt(ha, 10),
|
|
75
|
+
flags: parseInt(flags, 10),
|
|
76
|
+
iterations: parseInt(iterations, 10),
|
|
77
|
+
salt: salt,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fromTinydns(opts) {
|
|
82
|
+
const rd = opts.rd
|
|
83
|
+
|
|
84
|
+
// RDATA format: Hash Algorithm (3 octal chars) + Flags (3 octal chars) + Iterations (6 octal chars) + Salt (escaped hex string)
|
|
85
|
+
if (rd.length < 12) {
|
|
86
|
+
this.throwHelp(`NSEC3PARAM: RDATA too short: ${rd}`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return new NSEC3PARAM({
|
|
90
|
+
owner: this.fullyQualify(opts.owner),
|
|
91
|
+
ttl: parseInt(opts.ttl, 10),
|
|
92
|
+
type: 'NSEC3PARAM',
|
|
93
|
+
'hash algorithm': TINYDNS.octalToUInt8(rd.substring(0, 3)),
|
|
94
|
+
flags: TINYDNS.octalToUInt8(rd.substring(3, 6)),
|
|
95
|
+
iterations: TINYDNS.octalToUInt16(rd.substring(6, 12)),
|
|
96
|
+
salt: TINYDNS.unescapeOctal(rd.substring(12)),
|
|
78
97
|
})
|
|
79
98
|
}
|
|
80
99
|
|
|
81
100
|
/****** EXPORTERS *******/
|
|
101
|
+
|
|
102
|
+
toBind(zone_opts) {
|
|
103
|
+
// Example: test.example.com. 3600 IN NSEC3PARAM 1 1 12 aabbccdd
|
|
104
|
+
return `${this.getFQDN('owner', zone_opts)} ${this.get('ttl')} ${this.get('class')} NSEC3PARAM ${this.get('hash algorithm')} ${this.get('flags')} ${this.get('iterations')} ${this.get('salt')}
|
|
105
|
+
`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
toTinydns() {
|
|
109
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
110
|
+
|
|
111
|
+
let rdata = ''
|
|
112
|
+
rdata += TINYDNS.UInt8toOctal(this.get('hash algorithm'))
|
|
113
|
+
rdata += TINYDNS.UInt8toOctal(this.get('flags'))
|
|
114
|
+
rdata += TINYDNS.UInt16toOctal(this.get('iterations'))
|
|
115
|
+
rdata += TINYDNS.escapeOctal(dataRe, this.get('salt'))
|
|
116
|
+
|
|
117
|
+
return this.getTinydnsGeneric(rdata)
|
|
118
|
+
}
|
|
82
119
|
}
|
package/rr/nxt.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 NXT extends RR {
|
|
4
6
|
constructor(opts) {
|
|
5
7
|
super(opts)
|
|
@@ -41,6 +43,24 @@ export default class NXT extends RR {
|
|
|
41
43
|
|
|
42
44
|
/****** IMPORTERS *******/
|
|
43
45
|
|
|
46
|
+
fromTinydns(opts) {
|
|
47
|
+
const [owner, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
|
|
48
|
+
if (n != 30) this.throwHelp('NXT fromTinydns, invalid n')
|
|
49
|
+
|
|
50
|
+
const binaryRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
51
|
+
const [nextDomain, _escapedLen, binaryLen] = TINYDNS.unpackDomainName(rdata)
|
|
52
|
+
|
|
53
|
+
return new NXT({
|
|
54
|
+
owner: this.fullyQualify(owner),
|
|
55
|
+
ttl: parseInt(ttl, 10),
|
|
56
|
+
type: 'NXT',
|
|
57
|
+
'next domain': nextDomain,
|
|
58
|
+
'type bit map': binaryRdata.slice(binaryLen).toString(),
|
|
59
|
+
timestamp: ts,
|
|
60
|
+
location: loc !== '' && loc !== '\n' ? loc : '',
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
44
64
|
fromBind(opts) {
|
|
45
65
|
// test.example.com 3600 IN NXT NextDomain TypeBitMap
|
|
46
66
|
const [owner, ttl, c, type, next] = opts.bindline.split(/\s+/)
|
|
@@ -55,6 +75,14 @@ export default class NXT extends RR {
|
|
|
55
75
|
}
|
|
56
76
|
|
|
57
77
|
/****** EXPORTERS *******/
|
|
78
|
+
|
|
79
|
+
toTinydns() {
|
|
80
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
81
|
+
|
|
82
|
+
return this.getTinydnsGeneric(
|
|
83
|
+
TINYDNS.packDomainName(this.get('next domain')) + TINYDNS.escapeOctal(dataRe, this.get('type bit map')),
|
|
84
|
+
)
|
|
85
|
+
}
|
|
58
86
|
}
|
|
59
87
|
|
|
60
88
|
const removeParens = (a) => !['(', ')'].includes(a)
|
package/rr/openpgpkey.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
2
3
|
|
|
3
4
|
export default class OPENPGPKEY extends RR {
|
|
4
5
|
constructor(opts) {
|
|
@@ -42,5 +43,22 @@ export default class OPENPGPKEY extends RR {
|
|
|
42
43
|
})
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
fromTinydns(opts) {
|
|
47
|
+
return new OPENPGPKEY({
|
|
48
|
+
owner: this.fullyQualify(opts.owner),
|
|
49
|
+
ttl: parseInt(opts.ttl, 10),
|
|
50
|
+
type: 'OPENPGPKEY',
|
|
51
|
+
'public key': Buffer.from(TINYDNS.unescapeOctal(opts.rd), 'base64').toString('utf-8'),
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
/****** EXPORTERS *******/
|
|
56
|
+
toTinydns() {
|
|
57
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
58
|
+
const escapedPublicKey = TINYDNS.escapeOctal(
|
|
59
|
+
dataRe,
|
|
60
|
+
Buffer.from(this.get('public key'), 'utf-8').toString('base64'),
|
|
61
|
+
)
|
|
62
|
+
return this.getTinydnsGeneric(escapedPublicKey)
|
|
63
|
+
}
|
|
46
64
|
}
|
package/rr/sig.js
CHANGED
|
@@ -102,4 +102,14 @@ export default class SIG extends RR {
|
|
|
102
102
|
// }
|
|
103
103
|
|
|
104
104
|
/****** EXPORTERS *******/
|
|
105
|
+
|
|
106
|
+
toBind(zone_opts) {
|
|
107
|
+
return `${this.getFQDN('owner', zone_opts)} ${this.get('ttl')} ${this.get('class')} SIG${this.getRdataFields()
|
|
108
|
+
.slice(0, 4)
|
|
109
|
+
.map((f) => ' ' + this.get(f))
|
|
110
|
+
.join('')} ${this.getRdataFields()
|
|
111
|
+
.slice(4, 8)
|
|
112
|
+
.map((f) => this.get(f))
|
|
113
|
+
.join(' ')} ( ${this.get('signature')} )`
|
|
114
|
+
}
|
|
105
115
|
}
|
package/rr/smimea.js
CHANGED
|
@@ -91,6 +91,23 @@ export default class SMIMEA extends RR {
|
|
|
91
91
|
})
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
fromTinydns(opts) {
|
|
95
|
+
const [owner, _typeId, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
|
|
96
|
+
const binaryRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
97
|
+
|
|
98
|
+
return new SMIMEA({
|
|
99
|
+
owner: this.fullyQualify(owner),
|
|
100
|
+
ttl: parseInt(ttl, 10),
|
|
101
|
+
type: 'SMIMEA',
|
|
102
|
+
'certificate usage': binaryRdata.readUInt8(0),
|
|
103
|
+
selector: binaryRdata.readUInt8(1),
|
|
104
|
+
'matching type': binaryRdata.readUInt8(2),
|
|
105
|
+
'certificate association data': binaryRdata.slice(3).toString(),
|
|
106
|
+
timestamp: ts,
|
|
107
|
+
location: loc !== '' && loc !== '\n' ? loc : '',
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
94
111
|
/****** EXPORTERS *******/
|
|
95
112
|
toTinydns() {
|
|
96
113
|
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
package/rr/svcb.js
CHANGED
|
@@ -62,6 +62,29 @@ export default class SVCB extends RR {
|
|
|
62
62
|
})
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
fromTinydns({ rd, owner, ttl }) {
|
|
66
|
+
if (rd.length < 6) {
|
|
67
|
+
this.throwHelp(`SVCB: RDATA too short: ${rd}`)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const priority = TINYDNS.octalToUInt16(rd.substring(0, 6))
|
|
71
|
+
const remainingRdata = rd.slice(6)
|
|
72
|
+
|
|
73
|
+
const [targetName, consumedLength] = TINYDNS.unpackDomainName(remainingRdata)
|
|
74
|
+
|
|
75
|
+
const params = remainingRdata.slice(consumedLength)
|
|
76
|
+
const unescapedParams = TINYDNS.unescapeOctal(params)
|
|
77
|
+
|
|
78
|
+
return new SVCB({
|
|
79
|
+
owner: this.fullyQualify(owner),
|
|
80
|
+
ttl: parseInt(ttl, 10),
|
|
81
|
+
type: 'SVCB',
|
|
82
|
+
priority: priority,
|
|
83
|
+
'target name': targetName,
|
|
84
|
+
params: unescapedParams,
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
65
88
|
/****** EXPORTERS *******/
|
|
66
89
|
|
|
67
90
|
toTinydns() {
|
package/rr/tlsa.js
CHANGED
|
@@ -111,7 +111,7 @@ export default class TLSA extends RR {
|
|
|
111
111
|
'matching type': bytes.readUInt8(2),
|
|
112
112
|
'certificate association data': bytes.slice(3).toString(),
|
|
113
113
|
timestamp: ts,
|
|
114
|
-
location: loc
|
|
114
|
+
location: loc.trim() || '',
|
|
115
115
|
})
|
|
116
116
|
}
|
|
117
117
|
|