@nictool/dns-resource-record 1.2.0 → 1.2.2

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.
Files changed (81) hide show
  1. package/.codeclimate.yml +25 -0
  2. package/.github/FUNDING.yml +3 -0
  3. package/.github/workflows/ci.yml +43 -0
  4. package/.github/workflows/codeql.yml +14 -0
  5. package/.github/workflows/publish.yml +16 -0
  6. package/.gitmodules +3 -0
  7. package/CHANGELOG.md +18 -0
  8. package/DEVELOP.md +9 -0
  9. package/README.md +6 -2
  10. package/eslint.config.mjs +41 -0
  11. package/index.js +6 -0
  12. package/package.json +12 -3
  13. package/rr/a.js +13 -3
  14. package/rr/aaaa.js +14 -4
  15. package/rr/caa.js +25 -13
  16. package/rr/cname.js +3 -3
  17. package/rr/dname.js +4 -4
  18. package/rr/dnskey.js +6 -11
  19. package/rr/ds.js +6 -8
  20. package/rr/hinfo.js +8 -6
  21. package/rr/https.js +62 -0
  22. package/rr/ipseckey.js +20 -9
  23. package/rr/key.js +2 -2
  24. package/rr/loc.js +4 -4
  25. package/rr/mx.js +15 -3
  26. package/rr/naptr.js +2 -2
  27. package/rr/ns.js +1 -1
  28. package/rr/nsec.js +2 -4
  29. package/rr/nsec3.js +6 -12
  30. package/rr/nsec3param.js +4 -9
  31. package/rr/nxt.js +2 -4
  32. package/rr/openpgpkey.js +7 -3
  33. package/rr/rrsig.js +3 -4
  34. package/rr/sig.js +1 -1
  35. package/rr/smimea.js +3 -5
  36. package/rr/soa.js +1 -2
  37. package/rr/spf.js +1 -1
  38. package/rr/srv.js +4 -4
  39. package/rr/sshfp.js +1 -1
  40. package/rr/svcb.js +64 -0
  41. package/rr/tlsa.js +10 -10
  42. package/rr/tsig.js +10 -2
  43. package/rr/txt.js +5 -5
  44. package/rr/uri.js +2 -2
  45. package/rr/wks.js +4 -3
  46. package/rr.js +32 -20
  47. package/test/a.js +75 -0
  48. package/test/aaaa.js +86 -0
  49. package/test/base.js +148 -0
  50. package/test/caa.js +111 -0
  51. package/test/cert.js +48 -0
  52. package/test/cname.js +40 -0
  53. package/test/dname.js +57 -0
  54. package/test/dnskey.js +45 -0
  55. package/test/ds.js +45 -0
  56. package/test/fake.js +34 -0
  57. package/test/hinfo.js +80 -0
  58. package/test/https.js +56 -0
  59. package/test/ipseckey.js +141 -0
  60. package/test/key.js +36 -0
  61. package/test/loc.js +75 -0
  62. package/test/mx.js +78 -0
  63. package/test/naptr.js +47 -0
  64. package/test/ns.js +56 -0
  65. package/test/nsec.js +37 -0
  66. package/test/nsec3.js +47 -0
  67. package/test/nsec3param.js +23 -0
  68. package/test/nxt.js +37 -0
  69. package/test/openpgpkey.js +85 -0
  70. package/test/ptr.js +56 -0
  71. package/test/rr.js +212 -0
  72. package/test/smimea.js +51 -0
  73. package/test/soa.js +99 -0
  74. package/test/spf.js +51 -0
  75. package/test/srv.js +101 -0
  76. package/test/sshfp.js +69 -0
  77. package/test/svcb.js +56 -0
  78. package/test/tinydns.js +163 -0
  79. package/test/tlsa.js +63 -0
  80. package/test/txt.js +82 -0
  81. package/test/uri.js +65 -0
package/rr/https.js ADDED
@@ -0,0 +1,62 @@
1
+ import RR from '../rr.js'
2
+
3
+ export default class HTTPS extends RR {
4
+ constructor(opts) {
5
+ super(opts)
6
+ }
7
+
8
+ /****** Resource record specific setters *******/
9
+ setPriority(val) {
10
+ this.is16bitInt('HTTPS', 'priority', val)
11
+
12
+ this.set('priority', val)
13
+ }
14
+
15
+ setTargetName(val) {
16
+ // this.isFullyQualified('HTTPS', 'target name', val)
17
+ // this.isValidHostname('HTTPS', 'target name', val)
18
+
19
+ // RFC 4034: letters in the DNS names are lower cased
20
+ this.set('target name', val.toLowerCase())
21
+ }
22
+
23
+ setParams(val) {
24
+ // if (!val) this.throwHelp(`HTTPS: params is required`)
25
+
26
+ this.set('params', val)
27
+ }
28
+
29
+ getDescription() {
30
+ return 'HTTP Semantics'
31
+ }
32
+
33
+ getRdataFields(arg) {
34
+ return ['priority', 'target name', 'params']
35
+ }
36
+
37
+ getRFCs() {
38
+ return [9460]
39
+ }
40
+
41
+ getTypeId() {
42
+ return 65
43
+ }
44
+
45
+ /****** IMPORTERS *******/
46
+
47
+ fromBind(opts) {
48
+ // test.example.com 3600 IN HTTPS Priority TargetName Params
49
+ const [owner, ttl, c, type, pri, fqdn] = opts.bindline.split(/\s+/)
50
+ return new HTTPS({
51
+ owner,
52
+ ttl: parseInt(ttl, 10),
53
+ class: c,
54
+ type,
55
+ priority: parseInt(pri, 10),
56
+ 'target name': fqdn,
57
+ params: opts.bindline.split(/\s+/).slice(6).join(' ').trim(),
58
+ })
59
+ }
60
+
61
+ /****** EXPORTERS *******/
62
+ }
package/rr/ipseckey.js CHANGED
@@ -1,4 +1,4 @@
1
- import net from 'net'
1
+ import net from 'node:net'
2
2
 
3
3
  import RR from '../rr.js'
4
4
 
@@ -20,23 +20,20 @@ export default class IPSECKEY extends RR {
20
20
  setGatewayType(val) {
21
21
  // 0 (none), 1 (4-byte IPv4), 2 (16-byte IPv6), 3 (wire encoded domain name)
22
22
  if (![0, 1, 2, 3].includes(val))
23
- throw new Error(`IPSECKEY: Gateway Type is invalid, ${this.citeRFC()}`)
23
+ this.throwHelp(`IPSECKEY: Gateway Type is invalid`)
24
24
 
25
25
  this.set('gateway type', val)
26
26
  }
27
27
 
28
28
  setAlgorithm(val) {
29
29
  // unsigned int, 1 octet, values: 1=DSA, 2=RSA
30
- if (![1, 2].includes(val))
31
- throw new Error(`IPSECKEY: Algorithm invalid, ${this.citeRFC()}`)
30
+ if (![1, 2].includes(val)) this.throwHelp(`IPSECKEY: Algorithm invalid`)
32
31
 
33
32
  this.set('algorithm', val)
34
33
  }
35
34
 
36
35
  setGateway(val) {
37
- const gwErr = new Error(
38
- `IPSECKEY: gateway invalid (${val}), ${this.citeRFC()}`,
39
- )
36
+ const gwErr = new Error(`IPSECKEY: gateway invalid (${val})`)
40
37
  switch (this.get('gateway type')) {
41
38
  case 0:
42
39
  if (val !== '.') throw gwErr
@@ -53,7 +50,7 @@ export default class IPSECKEY extends RR {
53
50
  }
54
51
 
55
52
  setPublickey(val) {
56
- // if (val) throw new Error(`IPSECKEY: publickey is optional, ${this.citeRFC()}`)
53
+ // if (val) this.throwHelp(`IPSECKEY: publickey is optional`)
57
54
 
58
55
  this.set('publickey', val)
59
56
  }
@@ -74,6 +71,20 @@ export default class IPSECKEY extends RR {
74
71
  return 45
75
72
  }
76
73
 
74
+ getCanonical() {
75
+ return {
76
+ owner: '38.2.0.192.in-addr.arpa.',
77
+ ttl: 7200,
78
+ class: 'IN',
79
+ type: 'IPSECKEY',
80
+ precedence: 10,
81
+ 'gateway type': 1,
82
+ algorithm: 2,
83
+ gateway: '192.0.2.38',
84
+ publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==',
85
+ }
86
+ }
87
+
77
88
  /****** IMPORTERS *******/
78
89
  fromBind(opts) {
79
90
  // FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey
@@ -94,7 +105,7 @@ export default class IPSECKEY extends RR {
94
105
 
95
106
  fromTinydns(opts) {
96
107
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
97
- if (n != 45) throw new Error('IPSECKEY fromTinydns, invalid n')
108
+ if (n != 45) this.throwHelp('IPSECKEY fromTinydns, invalid n')
98
109
 
99
110
  const precedence = TINYDNS.octalToUInt8(rdata.substring(0, 4))
100
111
  const gwType = TINYDNS.octalToUInt8(rdata.substring(4, 8))
package/rr/key.js CHANGED
@@ -24,13 +24,13 @@ export default class KEY extends RR {
24
24
  // 1 octet
25
25
  // 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1
26
26
  if (![1, 2, 3, 4, 5, 253, 254].includes(val))
27
- throw new Error(`KEY: algorithm invalid, ${this.citeRFC()}`)
27
+ this.throwHelp(`KEY: algorithm invalid`)
28
28
 
29
29
  this.set('algorithm', val)
30
30
  }
31
31
 
32
32
  setPublickey(val) {
33
- if (!val) throw new Error(`KEY: publickey is required, ${this.citeRFC()}`)
33
+ if (!val) this.throwHelp(`KEY: publickey is required`)
34
34
 
35
35
  this.set('publickey', val)
36
36
  }
package/rr/loc.js CHANGED
@@ -20,7 +20,7 @@ export default class LOC extends RR {
20
20
 
21
21
  /****** Resource record specific setters *******/
22
22
  setAddress(val) {
23
- if (!val) throw new Error('LOC: address is required')
23
+ if (!val) this.throwHelp('LOC: address is required')
24
24
 
25
25
  /*
26
26
  ... LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]]
@@ -59,7 +59,7 @@ export default class LOC extends RR {
59
59
  // put them all together
60
60
  const locRe = new RegExp(`^${dms}(N|S)\\s+${dms}(E|W)\\s+${alt}`, 'i')
61
61
  const r = string.match(locRe)
62
- if (!r) throw new Error('LOC address: invalid format, see RFC 1876')
62
+ if (!r) this.throwHelp('LOC address: invalid format, see RFC 1876')
63
63
 
64
64
  const loc = {
65
65
  latitude: {
@@ -89,7 +89,7 @@ export default class LOC extends RR {
89
89
  fromTinydns(opts) {
90
90
  // LOC via generic, :fqdn:n:rdata:ttl:timestamp:lo
91
91
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
92
- if (n != 29) throw new Error('LOC fromTinydns, invalid n')
92
+ if (n != 29) this.throwHelp('LOC fromTinydns, invalid n')
93
93
 
94
94
  // divide by 100 is to convert cm to meters
95
95
  const l = {
@@ -173,7 +173,7 @@ export default class LOC extends RR {
173
173
  hem = rawmsec >= REF.LATLON ? 'E' : 'W'
174
174
  break
175
175
  default:
176
- throw new Error('unknown or missing hemisphere')
176
+ this.throwHelp('unknown or missing hemisphere')
177
177
  }
178
178
 
179
179
  return `${deg} ${min} ${sec}${msec ? '.' + msec : ''} ${hem}`
package/rr/mx.js CHANGED
@@ -1,4 +1,4 @@
1
- import net from 'net'
1
+ import net from 'node:net'
2
2
 
3
3
  import RR from '../rr.js'
4
4
 
@@ -10,15 +10,16 @@ export default class MX extends RR {
10
10
  /****** Resource record specific setters *******/
11
11
  setPreference(val) {
12
12
  if (val === undefined) val = this?.default?.preference
13
+ if (val === undefined) this.throwHelp('MX: preference is required')
13
14
  this.is16bitInt('MX', 'preference', val)
14
15
  this.set('preference', val)
15
16
  }
16
17
 
17
18
  setExchange(val) {
18
- if (!val) throw new Error('MX: exchange is required')
19
+ if (!val) this.throwHelp('MX: exchange is required')
19
20
 
20
21
  if (net.isIPv4(val) || net.isIPv6(val))
21
- throw new Error(`MX: exchange must be a FQDN, ${this.citeRFC()}`)
22
+ this.throwHelp(`MX: exchange must be a FQDN`)
22
23
 
23
24
  this.isFullyQualified('MX', 'exchange', val)
24
25
  this.isValidHostname('MX', 'exchange', val)
@@ -43,6 +44,17 @@ export default class MX extends RR {
43
44
  return 15
44
45
  }
45
46
 
47
+ getCanonical() {
48
+ return {
49
+ owner: 'example.com.',
50
+ ttl: 43200,
51
+ class: 'IN',
52
+ type: 'MX',
53
+ preference: 0,
54
+ exchange: 'mail.example.com.',
55
+ }
56
+ }
57
+
46
58
  /****** IMPORTERS *******/
47
59
  fromTinydns(opts) {
48
60
  // @fqdn:ip:x:dist:ttl:timestamp:lo
package/rr/naptr.js CHANGED
@@ -41,7 +41,7 @@ export default class NAPTR extends RR {
41
41
 
42
42
  setFlags(val) {
43
43
  if (!['', 'S', 'A', 'U', 'P'].includes(val.toUpperCase()))
44
- throw new Error(`NAPTR flags are invalid, ${this.citeRFC()}`)
44
+ this.throwHelp(`NAPTR flags are invalid`)
45
45
 
46
46
  this.set('flags', val.toUpperCase())
47
47
  }
@@ -62,7 +62,7 @@ export default class NAPTR extends RR {
62
62
  fromTinydns(opts) {
63
63
  // NAPTR via generic, :fqdn:n:rdata:ttl:timestamp:lo
64
64
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
65
- if (n != 35) throw new Error('NAPTR fromTinydns, invalid n')
65
+ if (n != 35) this.throwHelp('NAPTR fromTinydns, invalid n')
66
66
 
67
67
  const binRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
68
68
 
package/rr/ns.js CHANGED
@@ -8,7 +8,7 @@ export default class NS extends RR {
8
8
 
9
9
  /****** Resource record specific setters *******/
10
10
  setDname(val) {
11
- if (!val) throw new Error(`NS: dname is required, ${this.citeRFC()}`)
11
+ if (!val) this.throwHelp(`NS: dname is required`)
12
12
 
13
13
  this.isFullyQualified('NS', 'dname', val)
14
14
  this.isValidHostname('NS', 'dname', val)
package/rr/nsec.js CHANGED
@@ -8,8 +8,7 @@ export default class NSEC extends RR {
8
8
 
9
9
  /****** Resource record specific setters *******/
10
10
  setNextDomain(val) {
11
- if (!val)
12
- throw new Error(`NSEC: 'next domain' is required:, ${this.citeRFC()}`)
11
+ if (!val) this.throwHelp(`NSEC: 'next domain' is required:`)
13
12
 
14
13
  this.isFullyQualified('NSEC', 'next domain', val)
15
14
  this.isValidHostname('NSEC', 'next domain', val)
@@ -19,8 +18,7 @@ export default class NSEC extends RR {
19
18
  }
20
19
 
21
20
  setTypeBitMaps(val) {
22
- if (!val)
23
- throw new Error(`NSEC: 'type bit maps' is required, ${this.citeRFC()}`)
21
+ if (!val) this.throwHelp(`NSEC: 'type bit maps' is required`)
24
22
 
25
23
  this.set('type bit maps', val)
26
24
  }
package/rr/nsec3.js CHANGED
@@ -12,8 +12,7 @@ export default class NSEC3 extends RR {
12
12
  setHashAlgorithm(val) {
13
13
  // Hash Algorithm is a single octet.
14
14
  // The Hash Algorithm field is represented as an unsigned decimal integer.
15
- if (!val)
16
- throw new Error(`NSEC3: 'hash algorithm' is required, ${this.citeRFC()}`)
15
+ if (!val) this.throwHelp(`NSEC3: 'hash algorithm' is required`)
17
16
 
18
17
  this.is8bitInt('NSEC3', 'hash algorithm', val)
19
18
 
@@ -22,7 +21,7 @@ export default class NSEC3 extends RR {
22
21
 
23
22
  setFlags(val) {
24
23
  // The Flags field is represented as an unsigned decimal integer.
25
- if (!val) throw new Error(`NSEC3: 'flags' is required, ${this.citeRFC()}`)
24
+ if (!val) this.throwHelp(`NSEC3: 'flags' is required`)
26
25
 
27
26
  this.is8bitInt('NSEC3', 'flags', val)
28
27
 
@@ -31,8 +30,7 @@ export default class NSEC3 extends RR {
31
30
 
32
31
  setIterations(val) {
33
32
  // The Iterations field is represented as an unsigned decimal integer. 0-65535
34
- if (!val)
35
- throw new Error(`NSEC3: 'iterations' is required, ${this.citeRFC()}`)
33
+ if (!val) this.throwHelp(`NSEC3: 'iterations' is required`)
36
34
 
37
35
  this.is16bitInt('NSEC3', 'flags', val)
38
36
 
@@ -50,18 +48,14 @@ export default class NSEC3 extends RR {
50
48
  setNextHashedOwnerName(val) {
51
49
  // The Next Hashed Owner Name field is represented as an unpadded
52
50
  // sequence of case-insensitive base32 digits, without whitespace
53
- if (!val)
54
- throw new Error(
55
- `NSEC3: 'next hashed owner name' is required, ${this.citeRFC()}`,
56
- )
51
+ if (!val) this.throwHelp(`NSEC3: 'next hashed owner name' is required`)
57
52
 
58
53
  this.set('next hashed owner name', val)
59
54
  }
60
55
 
61
56
  setTypeBitMaps(val) {
62
57
  // The Type Bit Maps field is represented as a sequence of RR type mnemonics.
63
- if (!val)
64
- throw new Error(`NSEC3: 'type bit maps' is required, ${this.citeRFC()}`)
58
+ if (!val) this.throwHelp(`NSEC3: 'type bit maps' is required`)
65
59
 
66
60
  this.set('type bit maps', val)
67
61
  }
@@ -113,7 +107,7 @@ export default class NSEC3 extends RR {
113
107
 
114
108
  fromTinydns(opts) {
115
109
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
116
- if (n != 50) throw new Error('NSEC3 fromTinydns, invalid n')
110
+ if (n != 50) this.throwHelp('NSEC3 fromTinydns, invalid n')
117
111
 
118
112
  const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
119
113
 
package/rr/nsec3param.js CHANGED
@@ -7,13 +7,10 @@ export default class NSEC3PARAM extends RR {
7
7
  }
8
8
 
9
9
  /****** Resource record specific setters *******/
10
- setHashAlgoritm(val) {
10
+ setHashAlgorithm(val) {
11
11
  // Hash Algorithm is a single octet.
12
12
  // The Hash Algorithm field is represented as an unsigned decimal integer.
13
- if (!val)
14
- throw new Error(
15
- `NSEC3PARAM: 'hash algorithm' is required, ${this.citeRFC()}`,
16
- )
13
+ if (!val) this.throwHelp(`NSEC3PARAM: 'hash algorithm' is required`)
17
14
 
18
15
  this.is8bitInt('NSEC3PARAM', 'hash algorithm', val)
19
16
 
@@ -22,8 +19,7 @@ export default class NSEC3PARAM extends RR {
22
19
 
23
20
  setFlags(val) {
24
21
  // The Flags field is represented as an unsigned decimal integer.
25
- if (!val)
26
- throw new Error(`NSEC3PARAM: 'flags' is required, ${this.citeRFC()}`)
22
+ if (!val) this.throwHelp(`NSEC3PARAM: 'flags' is required`)
27
23
 
28
24
  this.is8bitInt('NSEC3PARAM', 'flags', val)
29
25
 
@@ -32,8 +28,7 @@ export default class NSEC3PARAM extends RR {
32
28
 
33
29
  setIterations(val) {
34
30
  // The Iterations field is represented as an unsigned decimal integer. 0-65535
35
- if (!val)
36
- throw new Error(`NSEC3PARAM: 'iterations' is required, ${this.citeRFC()}`)
31
+ if (!val) this.throwHelp(`NSEC3PARAM: 'iterations' is required`)
37
32
 
38
33
  this.is16bitInt('NSEC3PARAM', 'iterations', val)
39
34
 
package/rr/nxt.js CHANGED
@@ -8,8 +8,7 @@ export default class NXT extends RR {
8
8
 
9
9
  /****** Resource record specific setters *******/
10
10
  setNextDomain(val) {
11
- if (!val)
12
- throw new Error(`NXT: 'next domain' is required:, ${this.citeRFC()}`)
11
+ if (!val) this.throwHelp(`NXT: 'next domain' is required`)
13
12
 
14
13
  this.isFullyQualified('NXT', 'next domain', val)
15
14
  this.isValidHostname('NXT', 'next domain', val)
@@ -19,8 +18,7 @@ export default class NXT extends RR {
19
18
  }
20
19
 
21
20
  setTypeBitMap(val) {
22
- if (!val)
23
- throw new Error(`NXT: 'type bit map' is required, ${this.citeRFC()}`)
21
+ if (!val) this.throwHelp(`NXT: 'type bit map' is required`)
24
22
 
25
23
  this.set('type bit map', val)
26
24
  }
package/rr/openpgpkey.js CHANGED
@@ -27,15 +27,19 @@ export default class OPENPGPKEY extends RR {
27
27
  }
28
28
 
29
29
  /****** IMPORTERS *******/
30
- fromBind(str) {
30
+ fromBind(obj) {
31
31
  // test.example.com 3600 IN OPENPGPKEY <base64 public key>
32
- const [owner, ttl, c, type, privatekey] = str.split(/\s+/)
32
+ // 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]*)$/)
36
+
33
37
  return new OPENPGPKEY({
34
38
  owner,
35
39
  ttl: parseInt(ttl, 10),
36
40
  class: c,
37
41
  type: type,
38
- 'private key': privatekey,
42
+ 'public key': publickey.trim(),
39
43
  })
40
44
  }
41
45
 
package/rr/rrsig.js CHANGED
@@ -8,9 +8,8 @@ export default class RRSIG extends RR {
8
8
  /****** Resource record specific setters *******/
9
9
  setTypeCovered(val) {
10
10
  // a 2 octet Type Covered field
11
- if (!val) throw new Error(`RRSIG: 'type covered' is required`)
12
- if (val.length > 2)
13
- throw new Error(`RRSIG: 'type covered' is too long, ${this.citeRFC()}`)
11
+ if (!val) this.throwHelp(`RRSIG: 'type covered' is required`)
12
+ if (val.length > 2) this.throwHelp(`RRSIG: 'type covered' is too long`)
14
13
 
15
14
  this.set('type covered', val)
16
15
  }
@@ -19,7 +18,7 @@ export default class RRSIG extends RR {
19
18
  // a 1 octet Algorithm field
20
19
  // 1=RSA/MD5, 2=DH, 3=RRSIGA/SHA-1, 4=EC, 5=RSA/SHA-1
21
20
  if (![1, 2, 3, 4, 5, 253, 254].includes(val))
22
- throw new Error(`RRSIG: algorithm invalid, ${this.citeRFC()}`)
21
+ this.throwHelp(`RRSIG: algorithm invalid`)
23
22
 
24
23
  this.set('algorithm', val)
25
24
  }
package/rr/sig.js CHANGED
@@ -8,7 +8,7 @@ export default class SIG extends RR {
8
8
  /****** Resource record specific setters *******/
9
9
  setTypeCovered(val) {
10
10
  // a 2 octet Type Covered field
11
- if (!val) throw new Error(`SIG: 'type covered' is required`)
11
+ if (!val) this.throwHelp(`SIG: 'type covered' is required`)
12
12
 
13
13
  this.set('type covered', val)
14
14
  }
package/rr/smimea.js CHANGED
@@ -8,21 +8,19 @@ export default class SMIMEA extends RR {
8
8
  /****** Resource record specific setters *******/
9
9
  setCertificateUsage(val) {
10
10
  if (![0, 1, 2, 3].includes(val))
11
- throw new Error(`SMIMEA: certificate usage invalid, ${this.citeRFC()}`)
11
+ this.throwHelp(`SMIMEA: certificate usage invalid`)
12
12
 
13
13
  this.set('certificate usage', val)
14
14
  }
15
15
 
16
16
  setSelector(val) {
17
- if (![0, 1].includes(val))
18
- throw new Error(`SMIMEA: selector invalid, ${this.citeRFC()}`)
17
+ if (![0, 1].includes(val)) this.throwHelp(`SMIMEA: selector invalid`)
19
18
 
20
19
  this.set('selector', val)
21
20
  }
22
21
 
23
22
  setMatchingType(val) {
24
- if (![0, 1, 2].includes(val))
25
- throw new Error(`SMIMEA: matching type, ${this.citeRFC()}`)
23
+ if (![0, 1, 2].includes(val)) this.throwHelp(`SMIMEA: matching type`)
26
24
 
27
25
  this.set('matching type', val)
28
26
  }
package/rr/soa.js CHANGED
@@ -28,8 +28,7 @@ export default class SOA extends RR {
28
28
  // RNAME (email of admin) (escape . with \)
29
29
  this.isValidHostname('SOA', 'RNAME', val)
30
30
  this.isFullyQualified('SOA', 'RNAME', val)
31
- if (/@/.test(val))
32
- throw new Error(`SOA rname replaces @ with a . (dot), ${this.citeRFC()}`)
31
+ if (/@/.test(val)) this.throwHelp(`SOA rname replaces @ with a . (dot)`)
33
32
 
34
33
  // RFC 4034: letters in the DNS names are lower cased
35
34
  this.set('rname', val.toLowerCase())
package/rr/spf.js CHANGED
@@ -34,7 +34,7 @@ export default class SPF extends TXT {
34
34
  fromTinydns(opts) {
35
35
  // SPF via generic, :fqdn:n:rdata:ttl:timestamp:lo
36
36
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
37
- if (n != 99) throw new Error('SPF fromTinydns, invalid n')
37
+ if (n != 99) this.throwHelp('SPF fromTinydns, invalid n')
38
38
 
39
39
  return new SPF({
40
40
  type: 'SPF',
package/rr/srv.js CHANGED
@@ -1,4 +1,4 @@
1
- import net from 'net'
1
+ import net from 'node:net'
2
2
 
3
3
  import RR from '../rr.js'
4
4
  import * as TINYDNS from '../lib/tinydns.js'
@@ -28,10 +28,10 @@ export default class SRV extends RR {
28
28
  }
29
29
 
30
30
  setTarget(val) {
31
- if (!val) throw new Error(`SRV: target is required, ${this.citeRFC()}`)
31
+ if (!val) this.throwHelp(`SRV: target is required`)
32
32
 
33
33
  if (net.isIPv4(val) || net.isIPv6(val))
34
- throw new Error(`SRV: target must be a FQDN, ${this.citeRFC()}`)
34
+ this.throwHelp(`SRV: target must be a FQDN`)
35
35
 
36
36
  this.isFullyQualified('SRV', 'target', val)
37
37
  this.isValidHostname('SRV', 'target', val)
@@ -69,7 +69,7 @@ export default class SRV extends RR {
69
69
  } else {
70
70
  // tinydns generic record format
71
71
  ;[fqdn, n, rdata, ttl, ts, loc] = str.substring(1).split(':')
72
- if (n != 33) throw new Error('SRV fromTinydns: invalid n')
72
+ if (n != 33) this.throwHelp('SRV fromTinydns: invalid n')
73
73
 
74
74
  pri = TINYDNS.octalToUInt16(rdata.substring(0, 8))
75
75
  weight = TINYDNS.octalToUInt16(rdata.substring(8, 16))
package/rr/sshfp.js CHANGED
@@ -45,7 +45,7 @@ export default class SSHFP extends RR {
45
45
  fromTinydns(opts) {
46
46
  // SSHFP via generic, :fqdn:n:rdata:ttl:timestamp:lo
47
47
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
48
- if (n != 44) throw new Error('SSHFP fromTinydns, invalid n')
48
+ if (n != 44) this.throwHelp('SSHFP fromTinydns, invalid n')
49
49
 
50
50
  return new SSHFP({
51
51
  owner: this.fullyQualify(fqdn),
package/rr/svcb.js ADDED
@@ -0,0 +1,64 @@
1
+ import RR from '../rr.js'
2
+
3
+ export default class SVCB extends RR {
4
+ constructor(opts) {
5
+ super(opts)
6
+ }
7
+
8
+ /****** Resource record specific setters *******/
9
+ setPriority(val) {
10
+ this.is16bitInt('SVCB', 'priority', val)
11
+
12
+ this.set('priority', val)
13
+ }
14
+
15
+ setTargetName(val) {
16
+ // this.isFullyQualified('SVCB', 'target name', val)
17
+ // this.isValidHostname('SVCB', 'target name', val)
18
+
19
+ // RFC 4034: letters in the DNS names are lower cased
20
+ this.set('target name', val.toLowerCase())
21
+ }
22
+
23
+ setParams(val) {
24
+ // if (!val) throw new Error(`SVCB: params is required`)
25
+
26
+ this.set('params', val)
27
+ }
28
+
29
+ getDescription() {
30
+ return 'Service Binding'
31
+ }
32
+
33
+ getRdataFields(arg) {
34
+ return ['priority', 'target name', 'params']
35
+ }
36
+
37
+ getRFCs() {
38
+ return [9460]
39
+ }
40
+
41
+ getTypeId() {
42
+ return 64
43
+ }
44
+
45
+ /****** IMPORTERS *******/
46
+
47
+ fromBind(opts) {
48
+ // test.example.com 3600 IN SVCB Priority TargetName Params
49
+ // _8443._foo.api.example.com. 7200 IN SVCB 0 svc4.example.net.
50
+ // svc4.example.net. 7200 IN SVCB 3 svc4.example.net. ( alpn="bar" port="8004" )
51
+ const [owner, ttl, c, type, pri, fqdn] = opts.bindline.split(/\s+/)
52
+ return new SVCB({
53
+ owner,
54
+ ttl: parseInt(ttl, 10),
55
+ class: c,
56
+ type,
57
+ priority: parseInt(pri, 10),
58
+ 'target name': fqdn,
59
+ params: opts.bindline.split(/\s+/).slice(6).join(' ').trim(),
60
+ })
61
+ }
62
+
63
+ /****** EXPORTERS *******/
64
+ }
package/rr/tlsa.js CHANGED
@@ -10,21 +10,19 @@ export default class TLSA extends RR {
10
10
  /****** Resource record specific setters *******/
11
11
  setCertificateUsage(val) {
12
12
  if (![0, 1, 2, 3].includes(val))
13
- throw new Error(`TLSA: certificate usage invalid, ${this.citeRFC()}`)
13
+ this.throwHelp(`TLSA: certificate usage invalid`)
14
14
 
15
15
  this.set('certificate usage', val)
16
16
  }
17
17
 
18
18
  setSelector(val) {
19
- if (![0, 1].includes(val))
20
- throw new Error(`TLSA: selector invalid, ${this.citeRFC()}`)
19
+ if (![0, 1].includes(val)) this.throwHelp(`TLSA: selector invalid`)
21
20
 
22
21
  this.set('selector', val)
23
22
  }
24
23
 
25
24
  setMatchingType(val) {
26
- if (![0, 1, 2].includes(val))
27
- throw new Error(`TLSA: matching type, ${this.citeRFC()}`)
25
+ if (![0, 1, 2].includes(val)) this.throwHelp(`TLSA: matching type`)
28
26
 
29
27
  this.set('matching type', val)
30
28
  }
@@ -62,10 +60,12 @@ export default class TLSA extends RR {
62
60
 
63
61
  fromBind(opts) {
64
62
  // test.example.com 3600 IN TLSA, usage, selector, match, data
65
- const match = opts.bindline.split(
66
- /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+(.*?)\s*$/,
67
- )
68
- if (!match) throw new Error(`unable to parse TLSA: ${opts.bindline}`)
63
+ const match = opts.bindline
64
+ .trim()
65
+ .split(
66
+ /^([^\s]+)\s+([0-9]{1,10})\s+(IN)\s+(TLSA)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+(.*?)$/,
67
+ )
68
+ if (!match) this.throwHelp(`unable to parse TLSA: ${opts.bindline}`)
69
69
  const [owner, ttl, c, type, usage, selector, matchtype, cad] =
70
70
  match.slice(1)
71
71
  return new TLSA({
@@ -82,7 +82,7 @@ export default class TLSA extends RR {
82
82
 
83
83
  fromTinydns(opts) {
84
84
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
85
- if (n != 52) throw new Error('TLSA fromTinydns, invalid n')
85
+ if (n != 52) this.throwHelp('TLSA fromTinydns, invalid n')
86
86
 
87
87
  const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
88
88