@nictool/dns-resource-record 1.3.1 → 1.5.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 +28 -0
- package/README.md +20 -19
- package/lib/tinydns.js +45 -24
- package/package.json +9 -9
- package/rr/a.js +5 -5
- package/rr/aaaa.js +9 -9
- package/rr/apl.js +49 -2
- package/rr/caa.js +26 -23
- package/rr/cert.js +63 -4
- package/rr/cname.js +5 -5
- package/rr/dhcid.js +17 -2
- package/rr/dname.js +5 -5
- package/rr/dnskey.js +14 -8
- package/rr/ds.js +6 -6
- package/rr/hinfo.js +13 -10
- package/rr/hip.js +43 -2
- package/rr/https.js +37 -3
- package/rr/ipseckey.js +16 -16
- package/rr/key.js +34 -3
- package/rr/kx.js +18 -2
- package/rr/loc.js +14 -14
- package/rr/mx.js +5 -5
- package/rr/naptr.js +24 -20
- package/rr/ns.js +5 -5
- package/rr/nsec.js +19 -3
- package/rr/nsec3.js +74 -17
- package/rr/nsec3param.js +62 -12
- package/rr/nxt.js +31 -3
- package/rr/openpgpkey.js +28 -4
- package/rr/ptr.js +5 -5
- package/rr/rp.js +19 -2
- package/rr/rrsig.js +84 -10
- package/rr/sig.js +98 -12
- package/rr/smimea.js +20 -3
- package/rr/soa.js +6 -6
- package/rr/spf.js +3 -3
- package/rr/srv.js +11 -11
- package/rr/sshfp.js +8 -8
- package/rr/svcb.js +41 -3
- package/rr/tlsa.js +8 -8
- package/rr/tsig.js +139 -13
- package/rr/txt.js +10 -11
- package/rr/uri.js +8 -8
- package/rr/wks.js +26 -2
- package/rr.js +52 -7
package/rr/smimea.js
CHANGED
|
@@ -76,9 +76,9 @@ export default class SMIMEA extends RR {
|
|
|
76
76
|
|
|
77
77
|
/****** IMPORTERS *******/
|
|
78
78
|
|
|
79
|
-
fromBind(
|
|
79
|
+
fromBind({ bindline }) {
|
|
80
80
|
// test.example.com 3600 IN SMIMEA, usage, selector, match, data
|
|
81
|
-
const [owner, ttl, c, type, usage, selector, match] =
|
|
81
|
+
const [owner, ttl, c, type, usage, selector, match] = bindline.split(/\s+/)
|
|
82
82
|
return new SMIMEA({
|
|
83
83
|
owner,
|
|
84
84
|
ttl: parseInt(ttl, 10),
|
|
@@ -87,7 +87,24 @@ export default class SMIMEA extends RR {
|
|
|
87
87
|
'certificate usage': parseInt(usage, 10),
|
|
88
88
|
selector: parseInt(selector, 10),
|
|
89
89
|
'matching type': parseInt(match, 10),
|
|
90
|
-
'certificate association data':
|
|
90
|
+
'certificate association data': bindline.split(/\s+/).slice(7).join(' ').trim(),
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
fromTinydns({ tinyline }) {
|
|
95
|
+
const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(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?.trim() ?? '',
|
|
91
108
|
})
|
|
92
109
|
}
|
|
93
110
|
|
package/rr/soa.js
CHANGED
|
@@ -84,10 +84,10 @@ export default class SOA extends RR {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/****** IMPORTERS *******/
|
|
87
|
-
fromBind(
|
|
87
|
+
fromBind({ bindline }) {
|
|
88
88
|
// example.com TTL IN SOA mname rname serial refresh retry expire minimum
|
|
89
89
|
const [owner, ttl, c, type, mname, rname, serial, refresh, retry, expire, minimum] =
|
|
90
|
-
|
|
90
|
+
bindline.split(/[\s+]/)
|
|
91
91
|
|
|
92
92
|
return new SOA({
|
|
93
93
|
owner,
|
|
@@ -104,9 +104,9 @@ export default class SOA extends RR {
|
|
|
104
104
|
})
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
fromTinydns(
|
|
107
|
+
fromTinydns({ tinyline }) {
|
|
108
108
|
// Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:time:lo
|
|
109
|
-
const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] =
|
|
109
|
+
const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
110
110
|
|
|
111
111
|
return new SOA({
|
|
112
112
|
owner: this.fullyQualify(fqdn),
|
|
@@ -114,13 +114,13 @@ export default class SOA extends RR {
|
|
|
114
114
|
type: 'SOA',
|
|
115
115
|
mname: this.fullyQualify(mname),
|
|
116
116
|
rname: this.fullyQualify(rname),
|
|
117
|
-
serial: parseInt(ser
|
|
117
|
+
serial: parseInt(ser ?? this.default?.serial, 10),
|
|
118
118
|
refresh: parseInt(ref, 10) || 16384,
|
|
119
119
|
retry: parseInt(ret, 10) || 2048,
|
|
120
120
|
expire: parseInt(exp, 10) || 1048576,
|
|
121
121
|
minimum: parseInt(min, 10) || 2560,
|
|
122
122
|
timestamp: parseInt(ts) || '',
|
|
123
|
-
location: loc
|
|
123
|
+
location: loc?.trim() ?? '',
|
|
124
124
|
})
|
|
125
125
|
}
|
|
126
126
|
|
package/rr/spf.js
CHANGED
|
@@ -31,9 +31,9 @@ export default class SPF extends TXT {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/****** IMPORTERS *******/
|
|
34
|
-
fromTinydns(
|
|
34
|
+
fromTinydns({ tinyline }) {
|
|
35
35
|
// SPF via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
36
|
-
const [fqdn, n, rdata, ttl, ts, loc] =
|
|
36
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
37
37
|
if (n != 99) this.throwHelp('SPF fromTinydns, invalid n')
|
|
38
38
|
|
|
39
39
|
return new SPF({
|
|
@@ -42,7 +42,7 @@ export default class SPF extends TXT {
|
|
|
42
42
|
data: TINYDNS.octalToChar(rdata),
|
|
43
43
|
ttl: parseInt(ttl, 10),
|
|
44
44
|
timestamp: ts,
|
|
45
|
-
location: loc
|
|
45
|
+
location: loc?.trim() ?? '',
|
|
46
46
|
})
|
|
47
47
|
}
|
|
48
48
|
|
package/rr/srv.js
CHANGED
|
@@ -54,22 +54,22 @@ export default class SRV extends RR {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/****** IMPORTERS *******/
|
|
57
|
-
fromTinydns(
|
|
58
|
-
const str =
|
|
57
|
+
fromTinydns({ tinyline }) {
|
|
58
|
+
const str = tinyline
|
|
59
59
|
let fqdn, addr, port, pri, weight, ttl, ts, loc, n, rdata
|
|
60
60
|
|
|
61
61
|
if (str[0] === 'S') {
|
|
62
62
|
// patched tinydns with S records
|
|
63
|
-
;[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.
|
|
63
|
+
;[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.slice(1).split(':')
|
|
64
64
|
} else {
|
|
65
65
|
// tinydns generic record format
|
|
66
|
-
;[fqdn, n, rdata, ttl, ts, loc] = str.
|
|
66
|
+
;[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':')
|
|
67
67
|
if (n != 33) this.throwHelp('SRV fromTinydns: invalid n')
|
|
68
68
|
|
|
69
|
-
pri = TINYDNS.octalToUInt16(rdata.
|
|
70
|
-
weight = TINYDNS.octalToUInt16(rdata.
|
|
71
|
-
port = TINYDNS.octalToUInt16(rdata.
|
|
72
|
-
addr = TINYDNS.unpackDomainName(rdata.
|
|
69
|
+
pri = TINYDNS.octalToUInt16(rdata.slice(0, 8))
|
|
70
|
+
weight = TINYDNS.octalToUInt16(rdata.slice(8, 16))
|
|
71
|
+
port = TINYDNS.octalToUInt16(rdata.slice(16, 24))
|
|
72
|
+
addr = TINYDNS.unpackDomainName(rdata.slice(24))[0]
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
return new SRV({
|
|
@@ -81,13 +81,13 @@ export default class SRV extends RR {
|
|
|
81
81
|
port: parseInt(port, 10),
|
|
82
82
|
target: this.fullyQualify(addr),
|
|
83
83
|
timestamp: ts,
|
|
84
|
-
location: loc
|
|
84
|
+
location: loc?.trim() ?? '',
|
|
85
85
|
})
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
fromBind(
|
|
88
|
+
fromBind({ bindline }) {
|
|
89
89
|
// test.example.com 3600 IN SRV Priority Weight Port Target
|
|
90
|
-
const [owner, ttl, c, type, pri, weight, port, target] =
|
|
90
|
+
const [owner, ttl, c, type, pri, weight, port, target] = bindline.split(/\s+/)
|
|
91
91
|
return new SRV({
|
|
92
92
|
owner: owner,
|
|
93
93
|
ttl: parseInt(ttl, 10),
|
package/rr/sshfp.js
CHANGED
|
@@ -59,26 +59,26 @@ export default class SSHFP extends RR {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/****** IMPORTERS *******/
|
|
62
|
-
fromTinydns(
|
|
62
|
+
fromTinydns({ tinyline }) {
|
|
63
63
|
// SSHFP via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
64
|
-
const [fqdn, n, rdata, ttl, ts, loc] =
|
|
64
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
65
65
|
if (n != 44) this.throwHelp('SSHFP fromTinydns, invalid n')
|
|
66
66
|
|
|
67
67
|
return new SSHFP({
|
|
68
68
|
owner: this.fullyQualify(fqdn),
|
|
69
69
|
ttl: parseInt(ttl, 10),
|
|
70
70
|
type: 'SSHFP',
|
|
71
|
-
algorithm: TINYDNS.octalToUInt8(rdata.
|
|
72
|
-
fptype: TINYDNS.octalToUInt8(rdata.
|
|
73
|
-
fingerprint: TINYDNS.octalToHex(rdata.
|
|
71
|
+
algorithm: TINYDNS.octalToUInt8(rdata.slice(0, 4)),
|
|
72
|
+
fptype: TINYDNS.octalToUInt8(rdata.slice(4, 8)),
|
|
73
|
+
fingerprint: TINYDNS.octalToHex(rdata.slice(8)),
|
|
74
74
|
timestamp: ts,
|
|
75
|
-
location: loc
|
|
75
|
+
location: loc?.trim() ?? '',
|
|
76
76
|
})
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
fromBind(
|
|
79
|
+
fromBind({ bindline }) {
|
|
80
80
|
// test.example.com 3600 IN SSHFP algo fptype fp
|
|
81
|
-
const [owner, ttl, c, type, algo, fptype, fp] =
|
|
81
|
+
const [owner, ttl, c, type, algo, fptype, fp] = bindline.split(/\s+/)
|
|
82
82
|
return new SSHFP({
|
|
83
83
|
owner,
|
|
84
84
|
ttl: parseInt(ttl, 10),
|
package/rr/svcb.js
CHANGED
|
@@ -46,11 +46,11 @@ export default class SVCB extends RR {
|
|
|
46
46
|
|
|
47
47
|
/****** IMPORTERS *******/
|
|
48
48
|
|
|
49
|
-
fromBind(
|
|
49
|
+
fromBind({ bindline }) {
|
|
50
50
|
// test.example.com 3600 IN SVCB Priority TargetName Params
|
|
51
51
|
// _8443._foo.api.example.com. 7200 IN SVCB 0 svc4.example.net.
|
|
52
52
|
// svc4.example.net. 7200 IN SVCB 3 svc4.example.net. ( alpn="bar" port="8004" )
|
|
53
|
-
const [owner, ttl, c, type, pri, fqdn] =
|
|
53
|
+
const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\s+/)
|
|
54
54
|
return new SVCB({
|
|
55
55
|
owner,
|
|
56
56
|
ttl: parseInt(ttl, 10),
|
|
@@ -58,7 +58,45 @@ export default class SVCB extends RR {
|
|
|
58
58
|
type,
|
|
59
59
|
priority: parseInt(pri, 10),
|
|
60
60
|
'target name': fqdn,
|
|
61
|
-
params:
|
|
61
|
+
params: bindline.split(/\s+/).slice(6).join(' ').trim(),
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fromTinydns({ tinyline }) {
|
|
66
|
+
const [owner, _typeId, rd, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
67
|
+
|
|
68
|
+
if (rd.length < 6) {
|
|
69
|
+
this.throwHelp(`SVCB: RDATA too short: ${rd}`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Convert escaped octal RDATA into a binary buffer for reliable parsing
|
|
73
|
+
const binary = Buffer.from(TINYDNS.octalToChar(rd), 'binary')
|
|
74
|
+
|
|
75
|
+
const priority = binary.readUInt16BE(0)
|
|
76
|
+
|
|
77
|
+
// parse domain name from binary starting at offset 2
|
|
78
|
+
let pos = 2
|
|
79
|
+
const labels = []
|
|
80
|
+
while (true) {
|
|
81
|
+
const len = binary.readUInt8(pos)
|
|
82
|
+
pos += 1
|
|
83
|
+
if (len === 0) break
|
|
84
|
+
labels.push(binary.slice(pos, pos + len).toString())
|
|
85
|
+
pos += len
|
|
86
|
+
}
|
|
87
|
+
const targetName = `${labels.join('.')}.`
|
|
88
|
+
// remaining params are ASCII text after the domain
|
|
89
|
+
const params = binary.slice(pos).toString()
|
|
90
|
+
|
|
91
|
+
return new SVCB({
|
|
92
|
+
owner: this.fullyQualify(owner),
|
|
93
|
+
ttl: parseInt(ttl, 10),
|
|
94
|
+
type: 'SVCB',
|
|
95
|
+
priority: priority,
|
|
96
|
+
'target name': targetName,
|
|
97
|
+
params: params,
|
|
98
|
+
timestamp: ts,
|
|
99
|
+
location: loc?.trim() ?? '',
|
|
62
100
|
})
|
|
63
101
|
}
|
|
64
102
|
|
package/rr/tlsa.js
CHANGED
|
@@ -76,12 +76,12 @@ export default class TLSA extends RR {
|
|
|
76
76
|
|
|
77
77
|
/****** IMPORTERS *******/
|
|
78
78
|
|
|
79
|
-
fromBind(
|
|
79
|
+
fromBind({ bindline }) {
|
|
80
80
|
// test.example.com 3600 IN TLSA, usage, selector, match, data
|
|
81
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
|
|
83
|
-
const match =
|
|
84
|
-
if (!match) this.throwHelp(`unable to parse TLSA: ${
|
|
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>\S.*)$/i
|
|
83
|
+
const match = bindline.trim().match(regex)
|
|
84
|
+
if (!match) this.throwHelp(`unable to parse TLSA: ${bindline}`)
|
|
85
85
|
const { owner, ttl, cls, type, usage, selector, matchtype, cad } = match.groups
|
|
86
86
|
|
|
87
87
|
return new TLSA({
|
|
@@ -92,12 +92,12 @@ export default class TLSA extends RR {
|
|
|
92
92
|
'certificate usage': parseInt(usage, 10),
|
|
93
93
|
selector: parseInt(selector, 10),
|
|
94
94
|
'matching type': parseInt(matchtype, 10),
|
|
95
|
-
'certificate association data': cad,
|
|
95
|
+
'certificate association data': cad.trim(),
|
|
96
96
|
})
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
fromTinydns(
|
|
100
|
-
const [fqdn, n, rdata, ttl, ts, loc] =
|
|
99
|
+
fromTinydns({ tinyline }) {
|
|
100
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
101
101
|
if (n != 52) this.throwHelp('TLSA fromTinydns, invalid n')
|
|
102
102
|
|
|
103
103
|
const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
@@ -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
|
|
package/rr/tsig.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 TSIG extends RR {
|
|
4
5
|
constructor(opts) {
|
|
@@ -17,32 +18,157 @@ export default class TSIG extends RR {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
getRFCs() {
|
|
20
|
-
return [2845]
|
|
21
|
+
return [2845, 8945]
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
getTypeId() {
|
|
24
25
|
return 250
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
setClass(t) {
|
|
29
|
+
if (t !== 'ANY') this.throwHelp('TSIG: Class is required to be ANY')
|
|
30
|
+
this.set('class', t)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setTtl(t) {
|
|
34
|
+
if (t !== 0) this.throwHelp('TSIG: TTL is required to be 0')
|
|
35
|
+
this.set('ttl', t)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setAlgorithmName(val) {
|
|
39
|
+
if (!val) this.throwHelp(`TSIG: 'algorithm name' is required`)
|
|
40
|
+
this.set('algorithm name', val)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setTimeSigned(val) {
|
|
44
|
+
// a 48-bit unsigned integer, as seconds since the UNIX epoch
|
|
45
|
+
if (val === undefined) this.throwHelp(`TSIG: 'time signed' is required`)
|
|
46
|
+
this.set('time signed', val)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setFudge(val) {
|
|
50
|
+
// 16-bit unsigned
|
|
51
|
+
this.is16bitInt('TSIG', 'fudge', val)
|
|
52
|
+
this.set('fudge', val)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setMac(val) {
|
|
56
|
+
this.set('mac', val ?? '')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setOriginalId(val) {
|
|
60
|
+
this.is16bitInt('TSIG', 'original id', val)
|
|
61
|
+
this.set('original id', val)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setError(val) {
|
|
65
|
+
this.is16bitInt('TSIG', 'error', val)
|
|
66
|
+
this.set('error', val)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setOther(val) {
|
|
70
|
+
this.set('other', val ?? '')
|
|
71
|
+
}
|
|
72
|
+
|
|
27
73
|
/****** IMPORTERS *******/
|
|
28
74
|
|
|
29
|
-
fromBind(
|
|
30
|
-
//
|
|
31
|
-
const
|
|
75
|
+
fromBind({ bindline }) {
|
|
76
|
+
// owner ttl ANY TSIG alg time fudge mac_size mac original_id error other_len
|
|
77
|
+
const parts = bindline.trimEnd().split('\t')
|
|
78
|
+
const [owner, ttl, cls, type, alg, time, fudge, , mac, origId, error] = parts
|
|
79
|
+
|
|
32
80
|
return new TSIG({
|
|
33
81
|
owner,
|
|
34
82
|
ttl: parseInt(ttl, 10),
|
|
35
|
-
class:
|
|
36
|
-
type: type,
|
|
37
|
-
algorithm:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
83
|
+
class: cls,
|
|
84
|
+
type: type.toUpperCase(),
|
|
85
|
+
'algorithm name': alg,
|
|
86
|
+
'time signed': parseInt(time, 10),
|
|
87
|
+
fudge: parseInt(fudge, 10),
|
|
88
|
+
mac: mac || '',
|
|
89
|
+
'original id': parseInt(origId, 10),
|
|
90
|
+
error: parseInt(error, 10),
|
|
91
|
+
other: '',
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fromTinydns({ tinyline }) {
|
|
96
|
+
const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
97
|
+
|
|
98
|
+
const algUnpacked = TINYDNS.unpackDomainName(rdata)
|
|
99
|
+
const algBinaryLen = algUnpacked[2]
|
|
100
|
+
|
|
101
|
+
const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
102
|
+
let bpos = algBinaryLen
|
|
103
|
+
|
|
104
|
+
const timeSigned = bytes.readUInt32BE(bpos)
|
|
105
|
+
bpos += 4
|
|
106
|
+
const fudge = bytes.readUInt16BE(bpos)
|
|
107
|
+
bpos += 2
|
|
108
|
+
const macSize = bytes.readUInt16BE(bpos)
|
|
109
|
+
bpos += 2
|
|
110
|
+
const mac = macSize > 0 ? bytes.slice(bpos, bpos + macSize).toString('hex') : ''
|
|
111
|
+
bpos += macSize
|
|
112
|
+
const originalId = bytes.readUInt16BE(bpos)
|
|
113
|
+
bpos += 2
|
|
114
|
+
const error = bytes.readUInt16BE(bpos)
|
|
115
|
+
bpos += 2
|
|
116
|
+
const other = bpos < bytes.length ? bytes.slice(bpos).toString() : ''
|
|
117
|
+
|
|
118
|
+
return new TSIG({
|
|
119
|
+
owner: this.fullyQualify(owner),
|
|
120
|
+
ttl: parseInt(ttl, 10),
|
|
121
|
+
class: 'ANY',
|
|
122
|
+
type: 'TSIG',
|
|
123
|
+
'algorithm name': algUnpacked[0],
|
|
124
|
+
'time signed': timeSigned,
|
|
125
|
+
fudge,
|
|
126
|
+
mac,
|
|
127
|
+
'original id': originalId,
|
|
128
|
+
error,
|
|
129
|
+
other,
|
|
130
|
+
timestamp: ts,
|
|
131
|
+
location: loc?.trim() ?? '',
|
|
44
132
|
})
|
|
45
133
|
}
|
|
46
134
|
|
|
47
135
|
/****** EXPORTERS *******/
|
|
136
|
+
toBind(zone_opts) {
|
|
137
|
+
const mac = this.get('mac') ?? ''
|
|
138
|
+
const macSize = mac.length > 0 ? mac.length : ''
|
|
139
|
+
const other = this.get('other') ?? ''
|
|
140
|
+
const otherLen = other.length > 0 ? other.length : 0
|
|
141
|
+
return (
|
|
142
|
+
[
|
|
143
|
+
this.getFQDN('owner', zone_opts),
|
|
144
|
+
this.get('ttl'),
|
|
145
|
+
this.get('class'),
|
|
146
|
+
this.get('type'),
|
|
147
|
+
this.get('algorithm name'),
|
|
148
|
+
this.get('time signed'),
|
|
149
|
+
this.get('fudge'),
|
|
150
|
+
macSize,
|
|
151
|
+
mac,
|
|
152
|
+
this.get('original id'),
|
|
153
|
+
this.get('error'),
|
|
154
|
+
otherLen,
|
|
155
|
+
].join('\t') + '\n'
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
toTinydns() {
|
|
160
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
161
|
+
const alg = this.get('algorithm name') || ''
|
|
162
|
+
|
|
163
|
+
return this.getTinydnsGeneric(
|
|
164
|
+
TINYDNS.packDomainName(alg) +
|
|
165
|
+
TINYDNS.UInt32toOctal(this.get('time signed') ?? 0) +
|
|
166
|
+
TINYDNS.UInt16toOctal(this.get('fudge')) +
|
|
167
|
+
TINYDNS.UInt16toOctal(this.get('mac size') ?? 0) +
|
|
168
|
+
(this.get('mac size') > 0 ? TINYDNS.escapeOctal(dataRe, this.get('mac')) : '') +
|
|
169
|
+
TINYDNS.UInt16toOctal(this.get('original id') ?? 0) +
|
|
170
|
+
TINYDNS.UInt16toOctal(this.get('error') ?? 0) +
|
|
171
|
+
(this.get('other').length > 0 ? TINYDNS.escapeOctal(dataRe, this.get('other')) : ''),
|
|
172
|
+
)
|
|
173
|
+
}
|
|
48
174
|
}
|
package/rr/txt.js
CHANGED
|
@@ -29,12 +29,12 @@ export default class TXT extends RR {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/****** IMPORTERS *******/
|
|
32
|
-
fromTinydns(
|
|
33
|
-
const str =
|
|
32
|
+
fromTinydns({ tinyline }) {
|
|
33
|
+
const str = tinyline
|
|
34
34
|
let fqdn, rdata, s, ttl, ts, loc
|
|
35
35
|
// 'fqdn:s:ttl:timestamp:lo
|
|
36
36
|
if (str[0] === "'") {
|
|
37
|
-
;[fqdn, s, ttl, ts, loc] = str.
|
|
37
|
+
;[fqdn, s, ttl, ts, loc] = str.slice(1).split(':')
|
|
38
38
|
rdata = TINYDNS.octalToChar(s)
|
|
39
39
|
} else {
|
|
40
40
|
;[fqdn, rdata, ttl, ts, loc] = this.fromTinydnsGeneric(str)
|
|
@@ -46,14 +46,14 @@ export default class TXT extends RR {
|
|
|
46
46
|
type: 'TXT',
|
|
47
47
|
data: rdata,
|
|
48
48
|
timestamp: ts,
|
|
49
|
-
location: loc
|
|
49
|
+
location: loc?.trim() || '',
|
|
50
50
|
})
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
fromTinydnsGeneric(str) {
|
|
54
54
|
// generic: :fqdn:n:rdata:ttl:timestamp:location
|
|
55
55
|
// eslint-disable-next-line prefer-const
|
|
56
|
-
let [fqdn, n, rdata, ttl, ts, loc] = str.
|
|
56
|
+
let [fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':')
|
|
57
57
|
if (n != 16) this.throwHelp('TXT fromTinydns, invalid n')
|
|
58
58
|
|
|
59
59
|
rdata = TINYDNS.octalToChar(rdata)
|
|
@@ -61,19 +61,18 @@ export default class TXT extends RR {
|
|
|
61
61
|
let len = rdata[0].charCodeAt(0)
|
|
62
62
|
let pos = 1
|
|
63
63
|
while (pos < rdata.length) {
|
|
64
|
-
s += rdata.
|
|
64
|
+
s += rdata.slice(pos, +(len + pos))
|
|
65
65
|
pos = len + pos
|
|
66
66
|
len = rdata.charCodeAt(pos + 1)
|
|
67
67
|
}
|
|
68
68
|
return [fqdn, s, ttl, ts, loc]
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
fromBind(
|
|
71
|
+
fromBind({ bindline }) {
|
|
72
72
|
// test.example.com 3600 IN TXT "..."
|
|
73
|
-
const regex =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (!match) this.throwHelp(`unable to parse TXT: ${opts.bindline}`)
|
|
73
|
+
const regex = /^(?<owner>\S{1,255})\s+(?<ttl>\d{1,10})\s+(?<cls>IN)\s+(?<type>\w{3})\s+(?<rdata>\S.*)$/i
|
|
74
|
+
const match = bindline.trim().match(regex)
|
|
75
|
+
if (!match) this.throwHelp(`unable to parse TXT: ${bindline}`)
|
|
77
76
|
|
|
78
77
|
const { owner, ttl, cls, type, rdata } = match.groups
|
|
79
78
|
|
package/rr/uri.js
CHANGED
|
@@ -27,26 +27,26 @@ export default class URI extends RR {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/****** IMPORTERS *******/
|
|
30
|
-
fromTinydns(
|
|
30
|
+
fromTinydns({ tinyline }) {
|
|
31
31
|
// URI via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
32
|
-
const [fqdn, n, rdata, ttl, ts, loc] =
|
|
32
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
33
33
|
if (n != 256) this.throwHelp('URI fromTinydns, invalid n')
|
|
34
34
|
|
|
35
35
|
return new URI({
|
|
36
36
|
type: 'URI',
|
|
37
37
|
owner: this.fullyQualify(fqdn),
|
|
38
|
-
priority: TINYDNS.octalToUInt16(rdata.
|
|
39
|
-
weight: TINYDNS.octalToUInt16(rdata.
|
|
40
|
-
target: TINYDNS.octalToChar(rdata.
|
|
38
|
+
priority: TINYDNS.octalToUInt16(rdata.slice(0, 8)),
|
|
39
|
+
weight: TINYDNS.octalToUInt16(rdata.slice(8, 16)),
|
|
40
|
+
target: TINYDNS.octalToChar(rdata.slice(16)),
|
|
41
41
|
ttl: parseInt(ttl, 10),
|
|
42
42
|
timestamp: ts,
|
|
43
|
-
location: loc
|
|
43
|
+
location: loc?.trim() ?? '',
|
|
44
44
|
})
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
fromBind(
|
|
47
|
+
fromBind({ bindline }) {
|
|
48
48
|
// test.example.com 3600 IN URI priority, weight, target
|
|
49
|
-
const [owner, ttl, c, type, priority, weight, target] =
|
|
49
|
+
const [owner, ttl, c, type, priority, weight, target] = bindline.split(/\s+/)
|
|
50
50
|
return new URI({
|
|
51
51
|
class: c,
|
|
52
52
|
type: type,
|
package/rr/wks.js
CHANGED
|
@@ -43,9 +43,9 @@ export default class WKS extends RR {
|
|
|
43
43
|
|
|
44
44
|
/****** IMPORTERS *******/
|
|
45
45
|
|
|
46
|
-
fromBind(
|
|
46
|
+
fromBind({ bindline }) {
|
|
47
47
|
// test.example.com 3600 IN WKS 192.168.1.1 TCP ftp smtp
|
|
48
|
-
const parts =
|
|
48
|
+
const parts = bindline.split(/\s+/)
|
|
49
49
|
const [owner, ttl, c, type, address, protocol] = parts
|
|
50
50
|
return new WKS({
|
|
51
51
|
owner,
|
|
@@ -58,6 +58,30 @@ export default class WKS extends RR {
|
|
|
58
58
|
})
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
fromTinydns({ tinyline }) {
|
|
62
|
+
const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
63
|
+
|
|
64
|
+
const binary = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
65
|
+
const address = [binary.readUInt8(0), binary.readUInt8(1), binary.readUInt8(2), binary.readUInt8(3)].join(
|
|
66
|
+
'.',
|
|
67
|
+
)
|
|
68
|
+
const protoNum = binary.readUInt8(4)
|
|
69
|
+
const protoMap = { 6: 'TCP', 17: 'UDP' }
|
|
70
|
+
const protocol = protoMap[protoNum] ?? protoNum
|
|
71
|
+
const bitmap = binary.slice(5).toString()
|
|
72
|
+
|
|
73
|
+
return new WKS({
|
|
74
|
+
owner: this.fullyQualify(owner),
|
|
75
|
+
ttl: parseInt(ttl, 10),
|
|
76
|
+
type: 'WKS',
|
|
77
|
+
address,
|
|
78
|
+
protocol,
|
|
79
|
+
'bit map': bitmap,
|
|
80
|
+
timestamp: ts,
|
|
81
|
+
location: loc?.trim() ?? '',
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
61
85
|
/****** EXPORTERS *******/
|
|
62
86
|
|
|
63
87
|
toTinydns() {
|