@nictool/dns-resource-record 1.6.1 → 1.7.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 +33 -0
- package/README.md +323 -199
- package/dist/dns-rr.min.js +26 -0
- package/dist/dns-rr.min.js.map +7 -0
- package/index.js +12 -11
- package/lib/binary.js +108 -0
- package/lib/bind.js +94 -0
- package/lib/dns-query.js +67 -0
- package/lib/tinydns.js +128 -44
- package/lib/wire.js +519 -0
- package/package.json +23 -6
- package/rr/TEMPLATE.js +124 -0
- package/rr/a.js +8 -48
- package/rr/aaaa.js +13 -80
- package/rr/apl.js +123 -27
- package/rr/caa.js +27 -50
- package/rr/cert.js +58 -87
- package/rr/cname.js +7 -63
- package/rr/dhcid.js +20 -30
- package/rr/dname.js +9 -36
- package/rr/dnskey.js +38 -32
- package/rr/ds.js +43 -57
- package/rr/hinfo.js +21 -40
- package/rr/hip.js +88 -26
- package/rr/https.js +28 -40
- package/rr/ipseckey.js +97 -18
- package/rr/key.js +39 -29
- package/rr/kx.js +16 -27
- package/rr/loc.js +42 -12
- package/rr/mx.js +16 -51
- package/rr/naptr.js +58 -33
- package/rr/ns.js +8 -36
- package/rr/nsec.js +89 -18
- package/rr/nsec3.js +62 -26
- package/rr/nsec3param.js +56 -53
- package/rr/nxt.js +57 -18
- package/rr/openpgpkey.js +24 -30
- package/rr/ptr.js +7 -47
- package/rr/rp.js +17 -32
- package/rr/rrsig.js +80 -85
- package/rr/sig.js +70 -45
- package/rr/smimea.js +33 -33
- package/rr/soa.js +31 -49
- package/rr/spf.js +10 -17
- package/rr/srv.js +22 -62
- package/rr/sshfp.js +25 -53
- package/rr/svcb.js +27 -40
- package/rr/tlsa.js +34 -34
- package/rr/tsig.js +87 -24
- package/rr/txt.js +40 -59
- package/rr/uri.js +19 -29
- package/rr/wks.js +154 -22
- package/rr.js +290 -109
- package/lib/readme.js +0 -84
package/rr/a.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
2
|
|
|
3
3
|
export default class A extends RR {
|
|
4
|
+
static typeName = 'A'
|
|
5
|
+
static typeId = 1
|
|
6
|
+
static RFCs = [1035]
|
|
7
|
+
static tinydnsType = '+'
|
|
8
|
+
static rdataFields = [['address', 'ipv4']]
|
|
9
|
+
static tags = ['common']
|
|
10
|
+
|
|
4
11
|
constructor(opts) {
|
|
5
12
|
super(opts)
|
|
6
13
|
}
|
|
@@ -16,22 +23,6 @@ export default class A extends RR {
|
|
|
16
23
|
return 'Address'
|
|
17
24
|
}
|
|
18
25
|
|
|
19
|
-
getTags() {
|
|
20
|
-
return ['common']
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
getRdataFields(arg) {
|
|
24
|
-
return ['address']
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getRFCs() {
|
|
28
|
-
return [1035]
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getTypeId() {
|
|
32
|
-
return 1
|
|
33
|
-
}
|
|
34
|
-
|
|
35
26
|
getCanonical() {
|
|
36
27
|
return {
|
|
37
28
|
owner: 'host.example.com.',
|
|
@@ -42,39 +33,8 @@ export default class A extends RR {
|
|
|
42
33
|
}
|
|
43
34
|
}
|
|
44
35
|
|
|
45
|
-
/****** IMPORTERS *******/
|
|
46
|
-
fromTinydns({ tinyline }) {
|
|
47
|
-
// +fqdn:ip:ttl:timestamp:lo
|
|
48
|
-
const [owner, ip, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
49
|
-
|
|
50
|
-
return new A({
|
|
51
|
-
owner: this.fullyQualify(owner),
|
|
52
|
-
type: 'A',
|
|
53
|
-
address: ip,
|
|
54
|
-
ttl: parseInt(ttl, 10),
|
|
55
|
-
timestamp: ts,
|
|
56
|
-
location: loc?.trim() ?? '',
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
fromBind({ bindline }) {
|
|
61
|
-
// test.example.com 3600 IN A 192.0.2.127
|
|
62
|
-
const [owner, ttl, c, type, address] = bindline.split(/\s+/)
|
|
63
|
-
return new A({
|
|
64
|
-
owner,
|
|
65
|
-
ttl: parseInt(ttl, 10),
|
|
66
|
-
class: c,
|
|
67
|
-
type,
|
|
68
|
-
address,
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
|
|
72
36
|
/****** EXPORTERS *******/
|
|
73
37
|
getWireRdata() {
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
toTinydns() {
|
|
78
|
-
return `+${this.getTinyFQDN('owner')}:${this.get('address')}:${this.getTinydnsPostamble()}\n`
|
|
38
|
+
return new Uint8Array(this.get('address').split('.').map(Number))
|
|
79
39
|
}
|
|
80
40
|
}
|
package/rr/aaaa.js
CHANGED
|
@@ -2,6 +2,12 @@ import RR from '../rr.js'
|
|
|
2
2
|
import * as TINYDNS from '../lib/tinydns.js'
|
|
3
3
|
|
|
4
4
|
export default class AAAA extends RR {
|
|
5
|
+
static typeName = 'AAAA'
|
|
6
|
+
static typeId = 28
|
|
7
|
+
static RFCs = [3596, 5952]
|
|
8
|
+
static rdataFields = [['address', 'ipv6']]
|
|
9
|
+
static tags = ['common']
|
|
10
|
+
|
|
5
11
|
constructor(opts) {
|
|
6
12
|
super(opts)
|
|
7
13
|
}
|
|
@@ -11,33 +17,17 @@ export default class AAAA extends RR {
|
|
|
11
17
|
if (!val) this.throwHelp('AAAA: address is required')
|
|
12
18
|
if (!this.isIPv6(val)) this.throwHelp(`AAAA: address must be IPv6 (${val})`)
|
|
13
19
|
|
|
14
|
-
this.set('address', this.
|
|
20
|
+
this.set('address', this.expandIPv6(val.toLowerCase())) // lower case: RFC 5952
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
getCompressed(val) {
|
|
18
|
-
return this.
|
|
24
|
+
return this.compressIPv6(val ?? this.get('address'))
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
getDescription() {
|
|
22
28
|
return 'Address IPv6'
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
getTags() {
|
|
26
|
-
return ['common']
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
getRdataFields(arg) {
|
|
30
|
-
return ['address']
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getRFCs() {
|
|
34
|
-
return [3596, 5952]
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getTypeId() {
|
|
38
|
-
return 28
|
|
39
|
-
}
|
|
40
|
-
|
|
41
31
|
getCanonical() {
|
|
42
32
|
return {
|
|
43
33
|
owner: 'host.example.com.',
|
|
@@ -81,69 +71,12 @@ export default class AAAA extends RR {
|
|
|
81
71
|
})
|
|
82
72
|
}
|
|
83
73
|
|
|
84
|
-
fromBind({ bindline }) {
|
|
85
|
-
// test.example.com 3600 IN AAAA ...
|
|
86
|
-
const [owner, ttl, c, type, ip] = bindline.split(/\s+/)
|
|
87
|
-
return new AAAA({
|
|
88
|
-
owner,
|
|
89
|
-
ttl: parseInt(ttl, 10),
|
|
90
|
-
class: c,
|
|
91
|
-
type,
|
|
92
|
-
address: this.expand(ip),
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
compress(val) {
|
|
97
|
-
/*
|
|
98
|
-
* RFC 5952
|
|
99
|
-
* 4.1. Leading zeros MUST be suppressed...A single 16-bit 0000 field MUST be represented as 0.
|
|
100
|
-
* 4.2.1 The use of the symbol "::" MUST be used to its maximum capability.
|
|
101
|
-
* 4.2.2 The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field.
|
|
102
|
-
* 4.2.3 When choosing placement of a "::", the longest run...MUST be shortened
|
|
103
|
-
* 4.3 The characters a-f in an IPv6 address MUST be represented in lowercase.
|
|
104
|
-
*/
|
|
105
|
-
let r = val
|
|
106
|
-
.replace(/0000/g, '0') // 4.1 0000 -> 0
|
|
107
|
-
.replace(/:0+([1-9a-fA-F])/g, ':$1') // 4.1 remove leading zeros
|
|
108
|
-
|
|
109
|
-
const mostConsecutiveZeros = [
|
|
110
|
-
new RegExp(/0?(?::0){6,}:0?/),
|
|
111
|
-
new RegExp(/0?(?::0){5,}:0?/),
|
|
112
|
-
new RegExp(/0?(?::0){4,}:0?/),
|
|
113
|
-
new RegExp(/0?(?::0){3,}:0?/),
|
|
114
|
-
new RegExp(/0?(?::0){2,}:0?/),
|
|
115
|
-
]
|
|
116
|
-
|
|
117
|
-
for (const re of mostConsecutiveZeros) {
|
|
118
|
-
if (re.test(r)) {
|
|
119
|
-
r = r.replace(re, '::') // 4.2
|
|
120
|
-
break
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return r.toLowerCase() // 4.3
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
expand(val, delimiter) {
|
|
128
|
-
if (delimiter === undefined) delimiter = ':'
|
|
129
|
-
|
|
130
|
-
const colons = val.match(/:/g)
|
|
131
|
-
if (colons?.length < 7) {
|
|
132
|
-
// console.log(`AAAA: restoring compressed colons`)
|
|
133
|
-
val = val.replace(/::/, ':'.repeat(9 - colons.length))
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// restore compressed leading zeros
|
|
137
|
-
return val
|
|
138
|
-
.split(':')
|
|
139
|
-
.map((s) => s.padStart(4, 0))
|
|
140
|
-
.join(delimiter)
|
|
141
|
-
.toLowerCase()
|
|
142
|
-
}
|
|
143
|
-
|
|
144
74
|
/****** EXPORTERS *******/
|
|
145
75
|
getWireRdata() {
|
|
146
|
-
|
|
76
|
+
const hex = this.expandIPv6(this.get('address'), '')
|
|
77
|
+
const arr = new Uint8Array(hex.length / 2)
|
|
78
|
+
for (let i = 0; i < arr.length; i++) arr[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16)
|
|
79
|
+
return arr
|
|
147
80
|
}
|
|
148
81
|
|
|
149
82
|
toBind(zone_opts) {
|
|
@@ -152,7 +85,7 @@ export default class AAAA extends RR {
|
|
|
152
85
|
|
|
153
86
|
toTinydns() {
|
|
154
87
|
// from AAAA notation (8 groups of 4 hex digits) to 16 escaped octals
|
|
155
|
-
const rdata = TINYDNS.packHex(this.
|
|
88
|
+
const rdata = TINYDNS.packHex(this.expandIPv6(this.get('address'), ''))
|
|
156
89
|
return this.getTinydnsGeneric(rdata)
|
|
157
90
|
}
|
|
158
91
|
}
|
package/rr/apl.js
CHANGED
|
@@ -3,6 +3,11 @@ import RR from '../rr.js'
|
|
|
3
3
|
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
4
|
|
|
5
5
|
export default class APL extends RR {
|
|
6
|
+
static typeName = 'APL'
|
|
7
|
+
static typeId = 42
|
|
8
|
+
static RFCs = [3123]
|
|
9
|
+
static rdataFields = ['apl rdata']
|
|
10
|
+
|
|
6
11
|
constructor(opts) {
|
|
7
12
|
super(opts)
|
|
8
13
|
}
|
|
@@ -10,8 +15,6 @@ export default class APL extends RR {
|
|
|
10
15
|
/****** Resource record specific setters *******/
|
|
11
16
|
setAplRdata(val) {
|
|
12
17
|
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
18
|
this.set('apl rdata', val)
|
|
16
19
|
}
|
|
17
20
|
|
|
@@ -19,25 +22,13 @@ export default class APL extends RR {
|
|
|
19
22
|
return 'Address Prefix List'
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
getRdataFields(arg) {
|
|
23
|
-
return ['apl rdata']
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
getRFCs() {
|
|
27
|
-
return [3123]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
getTypeId() {
|
|
31
|
-
return 42
|
|
32
|
-
}
|
|
33
|
-
|
|
34
25
|
getCanonical() {
|
|
35
26
|
return {
|
|
36
27
|
owner: 'example.com.',
|
|
37
28
|
ttl: 3600,
|
|
38
29
|
class: 'IN',
|
|
39
30
|
type: 'APL',
|
|
40
|
-
'apl rdata': '1:192.0.2.
|
|
31
|
+
'apl rdata': '1:192.0.2.1/24 !1:192.0.2.64/28 2:2001:db8::1/128',
|
|
41
32
|
}
|
|
42
33
|
}
|
|
43
34
|
|
|
@@ -47,32 +38,33 @@ export default class APL extends RR {
|
|
|
47
38
|
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
48
39
|
if (n != 42) this.throwHelp('APL fromTinydns, invalid n')
|
|
49
40
|
|
|
50
|
-
const bytes =
|
|
41
|
+
const bytes = Uint8Array.from(TINYDNS.octalToChar(rdata), (c) => c.charCodeAt(0))
|
|
51
42
|
const items = []
|
|
52
43
|
let pos = 0
|
|
53
44
|
|
|
54
45
|
while (pos < bytes.length) {
|
|
55
|
-
const afi = bytes
|
|
46
|
+
const afi = (bytes[pos] << 8) | bytes[pos + 1]
|
|
56
47
|
pos += 2
|
|
57
|
-
const prefix = bytes
|
|
48
|
+
const prefix = bytes[pos]
|
|
58
49
|
pos++
|
|
59
|
-
const adfLenByte = bytes
|
|
50
|
+
const adfLenByte = bytes[pos]
|
|
60
51
|
pos++
|
|
61
52
|
const neg = (adfLenByte & 0x80) !== 0
|
|
62
53
|
const addrLen = adfLenByte & 0x7f
|
|
63
|
-
const addrBytes = bytes.
|
|
54
|
+
const addrBytes = bytes.subarray(pos, pos + addrLen)
|
|
64
55
|
pos += addrLen
|
|
65
56
|
|
|
66
57
|
let addr
|
|
67
58
|
if (afi === 1) {
|
|
68
|
-
const padded =
|
|
69
|
-
|
|
59
|
+
const padded = new Uint8Array(4)
|
|
60
|
+
padded.set(addrBytes)
|
|
70
61
|
addr = [...padded].join('.')
|
|
71
62
|
} else {
|
|
72
|
-
const padded =
|
|
73
|
-
|
|
63
|
+
const padded = new Uint8Array(16)
|
|
64
|
+
padded.set(addrBytes)
|
|
65
|
+
const paddedDv = new DataView(padded.buffer)
|
|
74
66
|
const groups = []
|
|
75
|
-
for (let i = 0; i < 16; i += 2) groups.push(
|
|
67
|
+
for (let i = 0; i < 16; i += 2) groups.push(paddedDv.getUint16(i).toString(16).padStart(4, '0'))
|
|
76
68
|
addr = this.compressIPv6(groups.join(':'))
|
|
77
69
|
}
|
|
78
70
|
|
|
@@ -102,6 +94,43 @@ export default class APL extends RR {
|
|
|
102
94
|
})
|
|
103
95
|
}
|
|
104
96
|
|
|
97
|
+
fromWire({ owner, cls, ttl, rdata }) {
|
|
98
|
+
const items = []
|
|
99
|
+
let pos = 0
|
|
100
|
+
while (pos < rdata.length) {
|
|
101
|
+
const afi = (rdata[pos] << 8) | rdata[pos + 1]
|
|
102
|
+
pos += 2
|
|
103
|
+
const prefix = rdata[pos++]
|
|
104
|
+
const adfLenByte = rdata[pos++]
|
|
105
|
+
const neg = (adfLenByte & 0x80) !== 0
|
|
106
|
+
const addrLen = adfLenByte & 0x7f
|
|
107
|
+
const addrBytes = rdata.subarray(pos, pos + addrLen)
|
|
108
|
+
pos += addrLen
|
|
109
|
+
|
|
110
|
+
let addr
|
|
111
|
+
if (afi === 1) {
|
|
112
|
+
const padded = new Uint8Array(4)
|
|
113
|
+
padded.set(addrBytes)
|
|
114
|
+
addr = [...padded].join('.')
|
|
115
|
+
} else {
|
|
116
|
+
const padded = new Uint8Array(16)
|
|
117
|
+
padded.set(addrBytes)
|
|
118
|
+
const dv = new DataView(padded.buffer)
|
|
119
|
+
const groups = []
|
|
120
|
+
for (let i = 0; i < 16; i += 2) groups.push(dv.getUint16(i).toString(16).padStart(4, '0'))
|
|
121
|
+
addr = this.compressIPv6(groups.join(':'))
|
|
122
|
+
}
|
|
123
|
+
items.push(`${neg ? '!' : ''}${afi}:${addr}/${prefix}`)
|
|
124
|
+
}
|
|
125
|
+
return new APL({
|
|
126
|
+
owner,
|
|
127
|
+
ttl,
|
|
128
|
+
class: cls,
|
|
129
|
+
type: 'APL',
|
|
130
|
+
'apl rdata': items.join(' '),
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
105
134
|
/****** EXPORTERS *******/
|
|
106
135
|
toTinydns() {
|
|
107
136
|
return this.getTinydnsGeneric(
|
|
@@ -119,7 +148,7 @@ export default class APL extends RR {
|
|
|
119
148
|
|
|
120
149
|
let addrBytes
|
|
121
150
|
if (afi === 1) {
|
|
122
|
-
addrBytes =
|
|
151
|
+
addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10)))
|
|
123
152
|
} else {
|
|
124
153
|
const dblIdx = addr.indexOf('::')
|
|
125
154
|
let groups
|
|
@@ -136,7 +165,10 @@ export default class APL extends RR {
|
|
|
136
165
|
} else {
|
|
137
166
|
groups = addr.split(':')
|
|
138
167
|
}
|
|
139
|
-
|
|
168
|
+
const hexStr = groups.map((g) => g.padStart(4, '0')).join('')
|
|
169
|
+
addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) =>
|
|
170
|
+
parseInt(hexStr.slice(i * 2, i * 2 + 2), 16),
|
|
171
|
+
)
|
|
140
172
|
}
|
|
141
173
|
|
|
142
174
|
let len = addrBytes.length
|
|
@@ -152,4 +184,68 @@ export default class APL extends RR {
|
|
|
152
184
|
.join(''),
|
|
153
185
|
)
|
|
154
186
|
}
|
|
187
|
+
|
|
188
|
+
getWireRdata() {
|
|
189
|
+
const items = this.get('apl rdata').split(/\s+/)
|
|
190
|
+
const rdata = []
|
|
191
|
+
|
|
192
|
+
for (const item of items) {
|
|
193
|
+
const neg = item.startsWith('!')
|
|
194
|
+
const bare = neg ? item.slice(1) : item
|
|
195
|
+
const colonIdx = bare.indexOf(':')
|
|
196
|
+
const afi = parseInt(bare.slice(0, colonIdx), 10)
|
|
197
|
+
const rest = bare.slice(colonIdx + 1)
|
|
198
|
+
const slashIdx = rest.lastIndexOf('/')
|
|
199
|
+
const addr = rest.slice(0, slashIdx)
|
|
200
|
+
const prefix = parseInt(rest.slice(slashIdx + 1), 10)
|
|
201
|
+
|
|
202
|
+
let addrBytes
|
|
203
|
+
if (afi === 1) {
|
|
204
|
+
addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10)))
|
|
205
|
+
} else {
|
|
206
|
+
const dblIdx = addr.indexOf('::')
|
|
207
|
+
let groups
|
|
208
|
+
if (dblIdx !== -1) {
|
|
209
|
+
const left = addr
|
|
210
|
+
.slice(0, dblIdx)
|
|
211
|
+
.split(':')
|
|
212
|
+
.filter((s) => s !== '')
|
|
213
|
+
const right = addr
|
|
214
|
+
.slice(dblIdx + 2)
|
|
215
|
+
.split(':')
|
|
216
|
+
.filter((s) => s !== '')
|
|
217
|
+
groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right]
|
|
218
|
+
} else {
|
|
219
|
+
groups = addr.split(':')
|
|
220
|
+
}
|
|
221
|
+
const hexStr = groups.map((g) => g.padStart(4, '0')).join('')
|
|
222
|
+
addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) =>
|
|
223
|
+
parseInt(hexStr.slice(i * 2, i * 2 + 2), 16),
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let len = addrBytes.length
|
|
228
|
+
while (len > 0 && addrBytes[len - 1] === 0) len--
|
|
229
|
+
const afdPart = addrBytes.slice(0, len)
|
|
230
|
+
|
|
231
|
+
const itemBytes = new Uint8Array(4 + afdPart.length)
|
|
232
|
+
const dv = new DataView(itemBytes.buffer, itemBytes.byteOffset)
|
|
233
|
+
dv.setUint16(0, afi)
|
|
234
|
+
itemBytes[2] = prefix
|
|
235
|
+
itemBytes[3] = (neg ? 0x80 : 0) | afdPart.length
|
|
236
|
+
itemBytes.set(afdPart, 4)
|
|
237
|
+
|
|
238
|
+
rdata.push(itemBytes)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const totalLen = rdata.reduce((sum, r) => sum + r.length, 0)
|
|
242
|
+
const bytes = new Uint8Array(totalLen)
|
|
243
|
+
let pos = 0
|
|
244
|
+
for (const r of rdata) {
|
|
245
|
+
bytes.set(r, pos)
|
|
246
|
+
pos += r.length
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return bytes
|
|
250
|
+
}
|
|
155
251
|
}
|
package/rr/caa.js
CHANGED
|
@@ -2,6 +2,16 @@ import RR from '../rr.js'
|
|
|
2
2
|
import * as TINYDNS from '../lib/tinydns.js'
|
|
3
3
|
|
|
4
4
|
export default class CAA extends RR {
|
|
5
|
+
static typeName = 'CAA'
|
|
6
|
+
static typeId = 257
|
|
7
|
+
static RFCs = [6844, 8659, 9619]
|
|
8
|
+
static rdataFields = [
|
|
9
|
+
['flags', 'u8'],
|
|
10
|
+
['tag', 'charstr'],
|
|
11
|
+
['value', 'qstr'],
|
|
12
|
+
]
|
|
13
|
+
static tags = ['security']
|
|
14
|
+
|
|
5
15
|
constructor(opts) {
|
|
6
16
|
super(opts)
|
|
7
17
|
}
|
|
@@ -62,26 +72,6 @@ export default class CAA extends RR {
|
|
|
62
72
|
return 'Certification Authority Authorization'
|
|
63
73
|
}
|
|
64
74
|
|
|
65
|
-
getTags() {
|
|
66
|
-
return ['security']
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
getQuotedFields() {
|
|
70
|
-
return ['value']
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getRdataFields(arg) {
|
|
74
|
-
return ['flags', 'tag', 'value']
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
getRFCs() {
|
|
78
|
-
return [6844, 8659]
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
getTypeId() {
|
|
82
|
-
return 257
|
|
83
|
-
}
|
|
84
|
-
|
|
85
75
|
getCanonical() {
|
|
86
76
|
return {
|
|
87
77
|
owner: 'example.com.',
|
|
@@ -97,8 +87,8 @@ export default class CAA extends RR {
|
|
|
97
87
|
/****** IMPORTERS *******/
|
|
98
88
|
fromTinydns({ tinyline }) {
|
|
99
89
|
// CAA via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
90
|
+
const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline)
|
|
91
|
+
if (typeId != this.getTypeId()) this.throwHelp('CAA fromTinydns, invalid typeId')
|
|
102
92
|
|
|
103
93
|
const flags = TINYDNS.octalToUInt8(rdata.slice(0, 4))
|
|
104
94
|
const taglen = TINYDNS.octalToUInt8(rdata.slice(4, 8))
|
|
@@ -108,49 +98,36 @@ export default class CAA extends RR {
|
|
|
108
98
|
const fingerprint = unescaped.slice(taglen)
|
|
109
99
|
|
|
110
100
|
return new CAA({
|
|
111
|
-
owner
|
|
112
|
-
ttl
|
|
101
|
+
owner,
|
|
102
|
+
ttl,
|
|
113
103
|
type: 'CAA',
|
|
114
104
|
flags,
|
|
115
105
|
tag,
|
|
116
106
|
value: fingerprint,
|
|
117
|
-
timestamp
|
|
118
|
-
location
|
|
107
|
+
timestamp,
|
|
108
|
+
location,
|
|
119
109
|
})
|
|
120
110
|
}
|
|
121
111
|
|
|
122
|
-
|
|
123
|
-
// test.example.com 3600 IN CAA flags, tags, value
|
|
124
|
-
const regex =
|
|
125
|
-
/^(?<owner>\S+)\s+(?<ttl>\d{1,10})\s+(?<class>IN)\s+(?<type>CAA)\s+(?<flags>\d+)\s+(?<tag>\w+)\s+(?:"(?<quotedValue>[^"]+)"|(?<unquotedValue>\S+))$/i
|
|
126
|
-
|
|
127
|
-
const match = bindline.trim().match(regex)
|
|
128
|
-
|
|
129
|
-
if (!match) {
|
|
130
|
-
this.throwHelp(`unable to parse CAA: ${bindline}`)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const { owner, ttl, class: c, type, flags, tag, quotedValue, unquotedValue } = match.groups
|
|
112
|
+
/****** EXPORTERS *******/
|
|
134
113
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
114
|
+
getWireRdata() {
|
|
115
|
+
const tag = new TextEncoder().encode(this.get('tag'))
|
|
116
|
+
const value = new TextEncoder().encode(this.get('value'))
|
|
117
|
+
const result = new Uint8Array(2 + tag.length + value.length)
|
|
118
|
+
result[0] = this.get('flags')
|
|
119
|
+
result[1] = tag.length
|
|
120
|
+
result.set(tag, 2)
|
|
121
|
+
result.set(value, 2 + tag.length)
|
|
122
|
+
return result
|
|
144
123
|
}
|
|
145
124
|
|
|
146
|
-
/****** EXPORTERS *******/
|
|
147
|
-
|
|
148
125
|
toTinydns() {
|
|
149
126
|
return this.getTinydnsGeneric(
|
|
150
127
|
TINYDNS.UInt8toOctal(this.get('flags')) +
|
|
151
128
|
TINYDNS.UInt8toOctal(this.get('tag').length) +
|
|
152
129
|
TINYDNS.escapeOctal(/[\r\n\t:\\/]/, this.get('tag')) +
|
|
153
|
-
TINYDNS.escapeOctal(/[\r\n\t:\\/]/, this.
|
|
130
|
+
TINYDNS.escapeOctal(/[\r\n\t:\\/]/, this.get('value')),
|
|
154
131
|
)
|
|
155
132
|
}
|
|
156
133
|
}
|