@nictool/dns-resource-record 1.1.7 → 1.2.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/.prettierrc.yml +3 -0
- package/CHANGELOG.md +17 -43
- package/README.md +45 -47
- package/index.js +77 -29
- package/lib/tinydns.js +68 -61
- package/package.json +1 -2
- package/rr/a.js +19 -20
- package/rr/aaaa.js +35 -31
- package/rr/caa.js +41 -39
- package/rr/cert.js +21 -19
- package/rr/cname.js +19 -20
- package/rr/dname.js +19 -19
- package/rr/dnskey.js +48 -41
- package/rr/ds.js +38 -36
- package/rr/hinfo.js +26 -25
- package/rr/ipseckey.js +53 -45
- package/rr/key.js +21 -21
- package/rr/loc.js +67 -54
- package/rr/mx.js +26 -24
- package/rr/naptr.js +51 -52
- package/rr/ns.js +25 -22
- package/rr/nsec.js +26 -20
- package/rr/nsec3.js +63 -44
- package/rr/nsec3param.js +29 -26
- package/rr/nxt.js +67 -0
- package/rr/openpgpkey.js +13 -14
- package/rr/ptr.js +20 -21
- package/rr/rrsig.js +27 -21
- package/rr/sig.js +24 -19
- package/rr/smimea.js +35 -28
- package/rr/soa.js +57 -42
- package/rr/spf.js +20 -17
- package/rr/srv.js +41 -41
- package/rr/sshfp.js +29 -30
- package/rr/tlsa.js +47 -40
- package/rr/tsig.js +48 -0
- package/rr/txt.js +40 -33
- package/rr/uri.js +31 -31
- package/rr/wks.js +44 -0
- package/rr.js +111 -77
- package/.codeclimate.yml +0 -25
- package/DEVELOP.md +0 -23
- package/test/a.js +0 -76
- package/test/aaaa.js +0 -79
- package/test/base.js +0 -138
- package/test/caa.js +0 -104
- package/test/cert.js +0 -48
- package/test/cname.js +0 -41
- package/test/dname.js +0 -53
- package/test/dnskey.js +0 -44
- package/test/ds.js +0 -44
- package/test/fake.js +0 -26
- package/test/hinfo.js +0 -75
- package/test/ipseckey.js +0 -115
- package/test/key.js +0 -37
- package/test/loc.js +0 -71
- package/test/mx.js +0 -75
- package/test/naptr.js +0 -40
- package/test/ns.js +0 -53
- package/test/nsec.js +0 -38
- package/test/nsec3.js +0 -40
- package/test/nsec3param.js +0 -26
- package/test/openpgpkey.js +0 -35
- package/test/ptr.js +0 -54
- package/test/rr.js +0 -196
- package/test/smimea.js +0 -45
- package/test/soa.js +0 -77
- package/test/spf.js +0 -48
- package/test/srv.js +0 -81
- package/test/sshfp.js +0 -62
- package/test/tinydns.js +0 -140
- package/test/tlsa.js +0 -54
- package/test/txt.js +0 -70
- package/test/uri.js +0 -61
package/rr.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
1
|
export default class RR extends Map {
|
|
3
|
-
constructor
|
|
2
|
+
constructor(opts) {
|
|
4
3
|
super()
|
|
5
4
|
|
|
6
5
|
if (opts === null) return
|
|
@@ -15,36 +14,40 @@ export default class RR extends Map {
|
|
|
15
14
|
this.setTimestamp(opts?.timestamp)
|
|
16
15
|
|
|
17
16
|
this.setOwner(opts?.owner)
|
|
18
|
-
this.setType
|
|
19
|
-
this.setTtl
|
|
17
|
+
this.setType(opts?.type)
|
|
18
|
+
this.setTtl(opts?.ttl)
|
|
20
19
|
this.setClass(opts?.class)
|
|
21
20
|
|
|
22
21
|
for (const f of this.getFields('rdata')) {
|
|
23
22
|
const fnName = `set${this.ucfirst(f)}`
|
|
24
|
-
if (this[fnName] === undefined)
|
|
23
|
+
if (this[fnName] === undefined)
|
|
24
|
+
throw new Error(`Missing ${fnName} in class ${this.get('type')}`)
|
|
25
25
|
this[fnName](opts[f])
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
if (opts.comment) this.set('comment', opts.comment)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
ucfirst
|
|
32
|
-
return str
|
|
31
|
+
ucfirst(str) {
|
|
32
|
+
return str
|
|
33
|
+
.split(/\s/)
|
|
34
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
35
|
+
.join('')
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
setClass
|
|
38
|
+
setClass(c) {
|
|
36
39
|
switch (c) {
|
|
37
|
-
case 'IN':
|
|
40
|
+
case 'IN': // 1
|
|
38
41
|
case undefined:
|
|
39
42
|
case null:
|
|
40
43
|
case '':
|
|
41
44
|
this.set('class', 'IN')
|
|
42
45
|
break
|
|
43
|
-
case 'CS':
|
|
44
|
-
case 'CH':
|
|
45
|
-
case 'HS':
|
|
46
|
-
case 'NONE':
|
|
47
|
-
case 'ANY':
|
|
46
|
+
case 'CS': // 2
|
|
47
|
+
case 'CH': // 3
|
|
48
|
+
case 'HS': // 4
|
|
49
|
+
case 'NONE': // 254
|
|
50
|
+
case 'ANY': // 255
|
|
48
51
|
this.set('class', c)
|
|
49
52
|
break
|
|
50
53
|
default:
|
|
@@ -52,7 +55,7 @@ export default class RR extends Map {
|
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
setLocation
|
|
58
|
+
setLocation(l) {
|
|
56
59
|
switch (l) {
|
|
57
60
|
case undefined:
|
|
58
61
|
return
|
|
@@ -61,7 +64,7 @@ export default class RR extends Map {
|
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
setTimestamp
|
|
67
|
+
setTimestamp(l) {
|
|
65
68
|
switch (l) {
|
|
66
69
|
case undefined:
|
|
67
70
|
return
|
|
@@ -70,32 +73,35 @@ export default class RR extends Map {
|
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
setOwner
|
|
76
|
+
setOwner(n) {
|
|
74
77
|
if (n === undefined) throw new Error(`owner is required`)
|
|
75
78
|
|
|
76
79
|
if (n.length < 1 || n.length > 255)
|
|
77
|
-
throw new Error(
|
|
80
|
+
throw new Error(
|
|
81
|
+
'Domain names must have 1-255 octets (characters): RFC 2181',
|
|
82
|
+
)
|
|
78
83
|
|
|
79
84
|
this.isFullyQualified('', 'owner', n)
|
|
80
85
|
this.hasValidLabels(n)
|
|
81
86
|
|
|
82
87
|
// wildcard records: RFC 1034, 4592
|
|
83
88
|
if (/\*/.test(n)) {
|
|
84
|
-
if (!/^\*\./.test(n) && !/\.\*\./.test(n))
|
|
89
|
+
if (!/^\*\./.test(n) && !/\.\*\./.test(n))
|
|
90
|
+
throw new Error('only *.something or * (by itself) is a valid wildcard')
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
this.set('owner', n.toLowerCase())
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
setTtl
|
|
91
|
-
|
|
96
|
+
setTtl(t) {
|
|
92
97
|
if (t === undefined) t = this?.default?.ttl
|
|
93
98
|
if (t === undefined) {
|
|
94
|
-
if ([
|
|
99
|
+
if (['SOA', 'SSHPF'].includes(this.get('type'))) return
|
|
95
100
|
throw new Error('TTL is required, no default available')
|
|
96
101
|
}
|
|
97
102
|
|
|
98
|
-
if (typeof t !== 'number')
|
|
103
|
+
if (typeof t !== 'number')
|
|
104
|
+
throw new Error(`TTL must be numeric (${typeof t})`)
|
|
99
105
|
|
|
100
106
|
// RFC 1035, 2181
|
|
101
107
|
this.is32bitInt(this.owner, 'TTL', t)
|
|
@@ -103,7 +109,7 @@ export default class RR extends Map {
|
|
|
103
109
|
this.set('ttl', t)
|
|
104
110
|
}
|
|
105
111
|
|
|
106
|
-
setType
|
|
112
|
+
setType(t) {
|
|
107
113
|
switch (t) {
|
|
108
114
|
case '':
|
|
109
115
|
case undefined:
|
|
@@ -116,11 +122,11 @@ export default class RR extends Map {
|
|
|
116
122
|
this.set('type', t.toUpperCase())
|
|
117
123
|
}
|
|
118
124
|
|
|
119
|
-
citeRFC
|
|
125
|
+
citeRFC() {
|
|
120
126
|
return `see RFC ${this.getRFCs()}`
|
|
121
127
|
}
|
|
122
128
|
|
|
123
|
-
fullyQualify
|
|
129
|
+
fullyQualify(hostname, origin) {
|
|
124
130
|
if (!hostname) return hostname
|
|
125
131
|
if (hostname === '@' && origin) hostname = origin
|
|
126
132
|
if (hostname.endsWith('.')) return hostname.toLowerCase()
|
|
@@ -128,7 +134,7 @@ export default class RR extends Map {
|
|
|
128
134
|
return `${hostname}.`
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
getPrefix
|
|
137
|
+
getPrefix(zone_opts = {}) {
|
|
132
138
|
const classVal = zone_opts.hide?.class ? '' : this.get('class')
|
|
133
139
|
|
|
134
140
|
let rrTTL = this.get('ttl')
|
|
@@ -137,25 +143,24 @@ export default class RR extends Map {
|
|
|
137
143
|
let owner = this.get('owner')
|
|
138
144
|
if (zone_opts.hide?.sameOwner && zone_opts.previousOwner === owner) {
|
|
139
145
|
owner = ''
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
146
|
+
} else {
|
|
142
147
|
owner = this.getFQDN('owner', zone_opts)
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
return `${owner}\t${rrTTL}\t${classVal}\t${this.get('type')}`
|
|
146
151
|
}
|
|
147
152
|
|
|
148
|
-
getEmpty
|
|
153
|
+
getEmpty(prop) {
|
|
149
154
|
return this.get(prop) === undefined ? '' : this.get(prop)
|
|
150
155
|
}
|
|
151
156
|
|
|
152
|
-
getComment
|
|
157
|
+
getComment(prop) {
|
|
153
158
|
const c = this.get('comment')
|
|
154
159
|
if (!c || !c[prop]) return ''
|
|
155
160
|
return c[prop]
|
|
156
161
|
}
|
|
157
162
|
|
|
158
|
-
getQuoted
|
|
163
|
+
getQuoted(prop) {
|
|
159
164
|
// if prop is not in quoted list, return bare
|
|
160
165
|
if (!this.getQuotedFields().includes(prop)) return this.get(prop)
|
|
161
166
|
|
|
@@ -165,16 +170,16 @@ export default class RR extends Map {
|
|
|
165
170
|
return `"${this.get(prop)}"` // add double quotes
|
|
166
171
|
}
|
|
167
172
|
|
|
168
|
-
getQuotedFields
|
|
173
|
+
getQuotedFields() {
|
|
169
174
|
return []
|
|
170
175
|
}
|
|
171
176
|
|
|
172
|
-
getRdataFields
|
|
177
|
+
getRdataFields() {
|
|
173
178
|
return []
|
|
174
179
|
}
|
|
175
180
|
|
|
176
|
-
getFields
|
|
177
|
-
const commonFields = [
|
|
181
|
+
getFields(arg) {
|
|
182
|
+
const commonFields = ['owner', 'ttl', 'class', 'type']
|
|
178
183
|
Object.freeze(commonFields)
|
|
179
184
|
|
|
180
185
|
switch (arg) {
|
|
@@ -187,23 +192,24 @@ export default class RR extends Map {
|
|
|
187
192
|
}
|
|
188
193
|
}
|
|
189
194
|
|
|
190
|
-
getFQDN
|
|
195
|
+
getFQDN(field, zone_opts = {}) {
|
|
191
196
|
let fqdn = this.get(field)
|
|
192
197
|
if (!fqdn) throw new Error(`empty value for field ${field}`)
|
|
193
198
|
if (!fqdn.endsWith('.')) fqdn += '.'
|
|
194
199
|
|
|
195
200
|
if (zone_opts.hide?.origin && zone_opts.origin) {
|
|
196
201
|
if (fqdn === zone_opts.origin) return '@'
|
|
197
|
-
if (fqdn.endsWith(zone_opts.origin))
|
|
202
|
+
if (fqdn.endsWith(zone_opts.origin))
|
|
203
|
+
return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1)
|
|
198
204
|
}
|
|
199
205
|
|
|
200
206
|
return fqdn
|
|
201
207
|
}
|
|
202
208
|
|
|
203
|
-
getTinyFQDN
|
|
209
|
+
getTinyFQDN(field) {
|
|
204
210
|
const val = this.get(field)
|
|
205
|
-
if (val === '') return val
|
|
206
|
-
if (val === '.') return val
|
|
211
|
+
if (val === '') return val // empty
|
|
212
|
+
if (val === '.') return val // null MX
|
|
207
213
|
|
|
208
214
|
// strip off trailing ., tinydns doesn't require it for FQDN
|
|
209
215
|
if (val.endsWith('.')) return val.slice(0, -1)
|
|
@@ -211,15 +217,17 @@ export default class RR extends Map {
|
|
|
211
217
|
return val
|
|
212
218
|
}
|
|
213
219
|
|
|
214
|
-
getTinydnsGeneric
|
|
220
|
+
getTinydnsGeneric(rdata) {
|
|
215
221
|
return `:${this.getTinyFQDN('owner')}:${this.getTypeId()}:${rdata}:${this.getTinydnsPostamble()}\n`
|
|
216
222
|
}
|
|
217
223
|
|
|
218
|
-
getTinydnsPostamble
|
|
219
|
-
return [
|
|
224
|
+
getTinydnsPostamble() {
|
|
225
|
+
return ['ttl', 'timestamp', 'location']
|
|
226
|
+
.map((f) => this.getEmpty(f))
|
|
227
|
+
.join(':')
|
|
220
228
|
}
|
|
221
229
|
|
|
222
|
-
hasValidLabels
|
|
230
|
+
hasValidLabels(hostname) {
|
|
223
231
|
// RFC 952 defined valid hostnames
|
|
224
232
|
// RFC 1035 limited domain label chars to letters, digits, and hyphen
|
|
225
233
|
// RFC 1123 allowed hostnames to start with a digit
|
|
@@ -231,64 +239,90 @@ export default class RR extends Map {
|
|
|
231
239
|
}
|
|
232
240
|
}
|
|
233
241
|
|
|
234
|
-
is8bitInt
|
|
235
|
-
if (
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
242
|
+
is8bitInt(type, field, value) {
|
|
243
|
+
if (
|
|
244
|
+
typeof value === 'number' &&
|
|
245
|
+
parseInt(value, 10) === value && // assure integer
|
|
246
|
+
value >= 0 &&
|
|
247
|
+
value <= 255
|
|
248
|
+
)
|
|
249
|
+
return true
|
|
250
|
+
|
|
251
|
+
throw new Error(
|
|
252
|
+
`${type} ${field} must be a 8-bit integer (in the range 0-255)`,
|
|
253
|
+
)
|
|
241
254
|
}
|
|
242
255
|
|
|
243
|
-
is16bitInt
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
256
|
+
is16bitInt(type, field, value) {
|
|
257
|
+
if (
|
|
258
|
+
typeof value === 'number' &&
|
|
259
|
+
parseInt(value, 10) === value && // assure integer
|
|
260
|
+
value >= 0 &&
|
|
261
|
+
value <= 65535
|
|
262
|
+
)
|
|
263
|
+
return true
|
|
264
|
+
|
|
265
|
+
throw new Error(
|
|
266
|
+
`${type} ${field} must be a 16-bit integer (in the range 0-65535)`,
|
|
267
|
+
)
|
|
250
268
|
}
|
|
251
269
|
|
|
252
|
-
is32bitInt
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
270
|
+
is32bitInt(type, field, value) {
|
|
271
|
+
if (
|
|
272
|
+
typeof value === 'number' &&
|
|
273
|
+
parseInt(value, 10) === value && // assure integer
|
|
274
|
+
value >= 0 &&
|
|
275
|
+
value <= 2147483647
|
|
276
|
+
)
|
|
277
|
+
return true
|
|
278
|
+
|
|
279
|
+
throw new Error(
|
|
280
|
+
`${type} ${field} must be a 32-bit integer (in the range 0-2147483647)`,
|
|
281
|
+
)
|
|
259
282
|
}
|
|
260
283
|
|
|
261
|
-
isQuoted
|
|
284
|
+
isQuoted(val) {
|
|
262
285
|
return /^["']/.test(val) && /["']$/.test(val)
|
|
263
286
|
}
|
|
264
287
|
|
|
265
|
-
isFullyQualified
|
|
288
|
+
isFullyQualified(type, blah, hostname) {
|
|
266
289
|
if (hostname.endsWith('.')) return true
|
|
267
290
|
|
|
268
291
|
throw new Error(`${type}: ${blah} must be fully qualified`)
|
|
269
292
|
}
|
|
270
293
|
|
|
271
|
-
isValidHostname
|
|
294
|
+
isValidHostname(type, field, hostname) {
|
|
272
295
|
const allowed = new RegExp(/[^a-zA-Z0-9\-._/\\]/)
|
|
273
296
|
if (!allowed.test(hostname)) return true
|
|
274
297
|
|
|
275
298
|
const matches = allowed.exec(hostname)
|
|
276
|
-
throw new Error(
|
|
299
|
+
throw new Error(
|
|
300
|
+
`${type}, ${field} has invalid hostname character (${matches[0]})`,
|
|
301
|
+
)
|
|
277
302
|
}
|
|
278
303
|
|
|
279
|
-
toBind
|
|
280
|
-
return `${this.getPrefix(zone_opts)}\t${this.getRdataFields()
|
|
304
|
+
toBind(zone_opts) {
|
|
305
|
+
return `${this.getPrefix(zone_opts)}\t${this.getRdataFields()
|
|
306
|
+
.map((f) => this.getQuoted(f))
|
|
307
|
+
.join('\t')}\n`
|
|
281
308
|
}
|
|
282
309
|
|
|
283
|
-
toMaraDNS
|
|
310
|
+
toMaraDNS() {
|
|
284
311
|
const type = this.get('type')
|
|
285
|
-
const supportedTypes =
|
|
312
|
+
const supportedTypes =
|
|
313
|
+
'A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC'.split(
|
|
314
|
+
/\s+/g,
|
|
315
|
+
)
|
|
286
316
|
if (!supportedTypes.includes(type)) return this.toMaraGeneric()
|
|
287
|
-
return `${this.get('owner')}\t+${this.get('ttl')}\t${type}\t${this.getRdataFields()
|
|
317
|
+
return `${this.get('owner')}\t+${this.get('ttl')}\t${type}\t${this.getRdataFields()
|
|
318
|
+
.map((f) => this.getQuoted(f))
|
|
319
|
+
.join('\t')} ~\n`
|
|
288
320
|
}
|
|
289
321
|
|
|
290
|
-
toMaraGeneric
|
|
322
|
+
toMaraGeneric() {
|
|
291
323
|
// throw new Error(`\nMaraDNS does not support ${type} records yet and this package does not support MaraDNS generic records. Yet.\n`)
|
|
292
|
-
return `${this.get('owner')}\t+${this.get('ttl')}\tRAW ${this.getTypeId()}\t'${this.getRdataFields()
|
|
324
|
+
return `${this.get('owner')}\t+${this.get('ttl')}\tRAW ${this.getTypeId()}\t'${this.getRdataFields()
|
|
325
|
+
.map((f) => this.getQuoted(f))
|
|
326
|
+
.join(' ')}' ~\n`
|
|
293
327
|
}
|
|
294
328
|
}
|
package/.codeclimate.yml
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
checks:
|
|
2
|
-
return-statements:
|
|
3
|
-
enabled: false
|
|
4
|
-
similar-code:
|
|
5
|
-
enabled: false
|
|
6
|
-
file-lines:
|
|
7
|
-
config:
|
|
8
|
-
threshold: 500
|
|
9
|
-
method-lines:
|
|
10
|
-
config:
|
|
11
|
-
threshold: 50
|
|
12
|
-
method-complexity:
|
|
13
|
-
config:
|
|
14
|
-
threshold: 10
|
|
15
|
-
|
|
16
|
-
plugins:
|
|
17
|
-
eslint:
|
|
18
|
-
enabled: true
|
|
19
|
-
channel: "eslint-8"
|
|
20
|
-
config:
|
|
21
|
-
config: ".eslintrc.yaml"
|
|
22
|
-
|
|
23
|
-
ratings:
|
|
24
|
-
paths:
|
|
25
|
-
- "**.js"
|
package/DEVELOP.md
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# Release process
|
|
3
|
-
|
|
4
|
-
In your local repo:
|
|
5
|
-
|
|
6
|
-
- make your changes
|
|
7
|
-
- git add .
|
|
8
|
-
- `.release/do.sh` {major|minor|patch}
|
|
9
|
-
- fill in the blanks in CHANGELOG.md
|
|
10
|
-
- `.release/push.sh`
|
|
11
|
-
|
|
12
|
-
Upon merge to `master`:
|
|
13
|
-
|
|
14
|
-
- the new version will be published to NPM.
|
|
15
|
-
- a GitHub release will be published.
|
|
16
|
-
- a release tag will be committed to the repo.
|
|
17
|
-
|
|
18
|
-
## Clean
|
|
19
|
-
|
|
20
|
-
`.release/cleanup.sh`
|
|
21
|
-
|
|
22
|
-
- will switch to the master branch
|
|
23
|
-
- delete the release branch
|
package/test/a.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import A from '../rr/a.js'
|
|
3
|
-
import * as base from './base.js'
|
|
4
|
-
|
|
5
|
-
const defaults = { class: 'IN', ttl: 3600, type: 'A', address: '192.0.2.127' }
|
|
6
|
-
|
|
7
|
-
const validRecords = [
|
|
8
|
-
{
|
|
9
|
-
...defaults,
|
|
10
|
-
owner: 'test.example.com.',
|
|
11
|
-
testB: 'test.example.com.\t3600\tIN\tA\t192.0.2.127\n',
|
|
12
|
-
testT: '+test.example.com:192.0.2.127:3600::\n',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
...defaults,
|
|
16
|
-
owner: 'test.example.com.',
|
|
17
|
-
ttl : 2147483647,
|
|
18
|
-
testB: 'test.example.com.\t2147483647\tIN\tA\t192.0.2.127\n',
|
|
19
|
-
testT: '+test.example.com:192.0.2.127:2147483647::\n',
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
...defaults,
|
|
23
|
-
owner: 'a.',
|
|
24
|
-
ttl : 86400,
|
|
25
|
-
testB: 'a.\t86400\tIN\tA\t192.0.2.127\n',
|
|
26
|
-
testT: '+a:192.0.2.127:86400::\n',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
...defaults,
|
|
30
|
-
owner: '*.example.com.',
|
|
31
|
-
testB: '*.example.com.\t3600\tIN\tA\t192.0.2.127\n',
|
|
32
|
-
testT: '+*.example.com:192.0.2.127:3600::\n',
|
|
33
|
-
},
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
const invalidRecords = [
|
|
37
|
-
{ ...defaults, owner: '', msg: /RFC/ },
|
|
38
|
-
{ ...defaults, owner: 'something*', msg: /fully/ },
|
|
39
|
-
{ ...defaults, owner: 'some*thing', msg: /fully/ },
|
|
40
|
-
{ ...defaults, owner: '*something', msg: /fully/ },
|
|
41
|
-
{ ...defaults, owner: 'something.*', msg: /fully/ },
|
|
42
|
-
{ ...defaults, address: 'hosts.not.valid.here', msg: /address must be IPv4/ },
|
|
43
|
-
{ ...defaults, address: '', msg: /address is required/ },
|
|
44
|
-
{ ...defaults, address: undefined, msg: /address is required/ },
|
|
45
|
-
{ ...defaults, address: '1.x.2.3', msg: /address must be IPv4/ },
|
|
46
|
-
{ ...defaults, address: '.1.2.3', msg: /address must be IPv4/ },
|
|
47
|
-
{ ...defaults, type: '', msg: /type is required/ },
|
|
48
|
-
{ ...defaults, type: undefined, msg: /type is required/ },
|
|
49
|
-
{ ...defaults, ttl: '', msg: /TTL must be numeric/ },
|
|
50
|
-
{ ...defaults, ttl: -299, msg: /TTL must be a 32-bit integer/ },
|
|
51
|
-
{ ...defaults, ttl: 2147483648, msg: /TTL must be a 32-bit integer/ },
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
// copy invalid properties to a valid object
|
|
55
|
-
for (let i = 0; i < invalidRecords.length; i++) {
|
|
56
|
-
const temp = JSON.parse(JSON.stringify(validRecords[0]))
|
|
57
|
-
Object.assign(temp, invalidRecords[i])
|
|
58
|
-
invalidRecords[i] = temp
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
describe('A record', function () {
|
|
62
|
-
base.valid(A, validRecords)
|
|
63
|
-
base.invalid(A, invalidRecords)
|
|
64
|
-
|
|
65
|
-
base.getDescription(A)
|
|
66
|
-
base.getRFCs(A, validRecords[0])
|
|
67
|
-
base.getRdataFields(A, [ 'address' ])
|
|
68
|
-
base.getFields(A, [ 'address' ])
|
|
69
|
-
base.getTypeId(A, 1)
|
|
70
|
-
|
|
71
|
-
base.toBind(A, validRecords)
|
|
72
|
-
base.toTinydns(A, validRecords)
|
|
73
|
-
|
|
74
|
-
base.fromBind(A, validRecords)
|
|
75
|
-
base.fromTinydns(A, validRecords)
|
|
76
|
-
})
|
package/test/aaaa.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import assert from 'assert'
|
|
3
|
-
|
|
4
|
-
import * as base from './base.js'
|
|
5
|
-
import AAAA from '../rr/aaaa.js'
|
|
6
|
-
|
|
7
|
-
const defaults = { class: 'IN', ttl: 3600, type: 'AAAA' }
|
|
8
|
-
|
|
9
|
-
const validRecords = [
|
|
10
|
-
{
|
|
11
|
-
...defaults,
|
|
12
|
-
owner : 'test.example.com.',
|
|
13
|
-
address: '2001:0db8:0020:000a:0000:0000:0000:0004',
|
|
14
|
-
testB : 'test.example.com.\t3600\tIN\tAAAA\t2001:db8:20:a::4\n',
|
|
15
|
-
testT : ':test.example.com:28:\\040\\001\\015\\270\\000\\040\\000\\012\\000\\000\\000\\000\\000\\000\\000\\004:3600::\n',
|
|
16
|
-
},
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
const invalidRecords = [
|
|
20
|
-
{
|
|
21
|
-
...defaults,
|
|
22
|
-
owner : 'test.example.com.',
|
|
23
|
-
address: '192.0.2.204',
|
|
24
|
-
msg : /address must be IPv6/,
|
|
25
|
-
},
|
|
26
|
-
]
|
|
27
|
-
|
|
28
|
-
describe('AAAA record', function () {
|
|
29
|
-
base.valid(AAAA, validRecords)
|
|
30
|
-
base.invalid(AAAA, invalidRecords)
|
|
31
|
-
|
|
32
|
-
base.getDescription(AAAA)
|
|
33
|
-
base.getRFCs(AAAA, validRecords[0])
|
|
34
|
-
base.getFields(AAAA, [ 'address' ])
|
|
35
|
-
base.getTypeId(AAAA, 28)
|
|
36
|
-
|
|
37
|
-
base.toBind(AAAA, validRecords)
|
|
38
|
-
base.toTinydns(AAAA, validRecords)
|
|
39
|
-
|
|
40
|
-
base.fromBind(AAAA, validRecords)
|
|
41
|
-
base.fromTinydns(AAAA, validRecords)
|
|
42
|
-
|
|
43
|
-
for (const val of validRecords) {
|
|
44
|
-
it(`imports tinydns AAAA (generic) record (${val.owner})`, async function () {
|
|
45
|
-
const r = new AAAA({ tinyline: val.testT })
|
|
46
|
-
if (process.env.DEBUG) console.dir(r)
|
|
47
|
-
for (const f of [ 'owner', 'address', 'ttl' ]) {
|
|
48
|
-
assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`)
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const tests = [
|
|
54
|
-
{ e: '2001:0db8:0020:000a:0000:0000:0000:0004', c: '2001:db8:20:a::4' },
|
|
55
|
-
{ e: '0000:0000:0000:0000:0000:0000:0000:0000', c: '::' },
|
|
56
|
-
{ e: '0000:0000:0000:0000:0000:0000:0000:0001', c: '::1' },
|
|
57
|
-
{ e: '2001:0db8:0000:0000:0000:0000:0002:0001', c: '2001:db8::2:1' },
|
|
58
|
-
{ e: '2001:0db8:0000:0001:0001:0001:0001:0001', c: '2001:db8:0:1:1:1:1:1' },
|
|
59
|
-
{ e: '2001:0DB8:0000:0000:0008:0800:200C:417A', c: '2001:DB8::8:800:200C:417A' },
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
describe('compress', function () {
|
|
63
|
-
const r = new AAAA(null)
|
|
64
|
-
for (const t of tests) {
|
|
65
|
-
it(`compresses IPv6 address (${t.e})`, function () {
|
|
66
|
-
assert.equal(r.compress(t.e), t.c)
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
describe('expand', function () {
|
|
72
|
-
const r = new AAAA(null)
|
|
73
|
-
for (const t of tests) {
|
|
74
|
-
it(`expands IPv6 address (${t.c})`, function () {
|
|
75
|
-
assert.equal(r.expand(t.c), t.e)
|
|
76
|
-
})
|
|
77
|
-
}
|
|
78
|
-
})
|
|
79
|
-
})
|