@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/rr/dname.js CHANGED
@@ -36,9 +36,9 @@ export default class DNAME extends RR {
36
36
  }
37
37
 
38
38
  /****** IMPORTERS *******/
39
- fromTinydns(opts) {
39
+ fromTinydns({ tinyline }) {
40
40
  // DNAME via generic, :fqdn:n:rdata:ttl:timestamp:lo
41
- const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
41
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
42
42
  if (n != 39) this.throwHelp('DNAME fromTinydns, invalid n')
43
43
 
44
44
  return new DNAME({
@@ -47,13 +47,13 @@ export default class DNAME extends RR {
47
47
  target: TINYDNS.unpackDomainName(rdata)[0],
48
48
  ttl: parseInt(ttl, 10),
49
49
  timestamp: ts,
50
- location: loc !== '' && loc !== '\n' ? loc : '',
50
+ location: loc?.trim() ?? '',
51
51
  })
52
52
  }
53
53
 
54
- fromBind(opts) {
54
+ fromBind({ bindline }) {
55
55
  // test.example.com 3600 IN DNAME ...
56
- const [owner, ttl, c, type, target] = opts.bindline.split(/\s+/)
56
+ const [owner, ttl, c, type, target] = bindline.split(/\s+/)
57
57
  return new DNAME({
58
58
  owner,
59
59
  ttl: parseInt(ttl, 10),
package/rr/dnskey.js CHANGED
@@ -93,12 +93,18 @@ export default class DNSKEY extends RR {
93
93
 
94
94
  /****** IMPORTERS *******/
95
95
 
96
- fromBind(opts) {
96
+ fromBind({ bindline }) {
97
97
  // test.example.com 3600 IN DNSKEY Flags Protocol Algorithm PublicKey
98
- const regex = /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+\s*(.*?)\s*$/
99
- const match = opts.bindline.match(regex)
100
- if (!match) this.throwHelp(`unable to parse DNSKEY: ${opts.bindline}`)
101
- const [owner, ttl, c, type, flags, protocol, algorithm, publickey] = match.slice(1)
98
+ const regex =
99
+ /^(?<owner>\S+)\s+(?<ttl>\d+)\s+(?<cls>\w+)\s+(?<type>DNSKEY)\s+(?<flags>\d+)\s+(?<protocol>\d+)\s+(?<algorithm>\d+)\s+(?<publickey>\S.*)$/i
100
+
101
+ const match = bindline.trim().match(regex)
102
+
103
+ if (!match) {
104
+ this.throwHelp(`unable to parse DNSKEY: ${bindline}`)
105
+ }
106
+
107
+ const { owner, ttl, c, type, flags, protocol, algorithm, publickey } = match.groups
102
108
 
103
109
  return new DNSKEY({
104
110
  owner,
@@ -112,8 +118,8 @@ export default class DNSKEY extends RR {
112
118
  })
113
119
  }
114
120
 
115
- fromTinydns(opts) {
116
- const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
121
+ fromTinydns({ tinyline }) {
122
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.substring(1).split(':')
117
123
  if (n != 48) this.throwHelp('DNSKEY fromTinydns, invalid n')
118
124
 
119
125
  const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
@@ -127,7 +133,7 @@ export default class DNSKEY extends RR {
127
133
  algorithm: bytes.readUInt8(3),
128
134
  publickey: bytes.slice(4).toString(),
129
135
  timestamp: ts,
130
- location: loc !== '' && loc !== '\n' ? loc : '',
136
+ location: loc?.trim() ?? '',
131
137
  })
132
138
  }
133
139
 
package/rr/ds.js CHANGED
@@ -64,9 +64,9 @@ export default class DS extends RR {
64
64
 
65
65
  /****** IMPORTERS *******/
66
66
 
67
- fromBind(opts) {
67
+ fromBind({ bindline }) {
68
68
  // test.example.com 3600 IN DS Key Tag Algorithm, Digest Type, Digest
69
- const [owner, ttl, c, type, keytag, algorithm, digesttype] = opts.bindline.split(/\s+/)
69
+ const [owner, ttl, c, type, keytag, algorithm, digesttype] = bindline.split(/\s+/)
70
70
  return new DS({
71
71
  owner,
72
72
  ttl: parseInt(ttl, 10),
@@ -75,12 +75,12 @@ export default class DS extends RR {
75
75
  'key tag': parseInt(keytag, 10),
76
76
  algorithm: parseInt(algorithm, 10),
77
77
  'digest type': parseInt(digesttype, 10),
78
- digest: opts.bindline.split(/\s+/).slice(7).join(' ').trim(),
78
+ digest: bindline.split(/\s+/).slice(7).join(' ').trim(),
79
79
  })
80
80
  }
81
81
 
82
- fromTinydns(opts) {
83
- const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
82
+ fromTinydns({ tinyline }) {
83
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
84
84
  if (n != 43) this.throwHelp('DS fromTinydns, invalid n')
85
85
 
86
86
  const binRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
@@ -94,7 +94,7 @@ export default class DS extends RR {
94
94
  'digest type': binRdata.readUInt8(3),
95
95
  digest: binRdata.slice(4).toString(),
96
96
  timestamp: ts,
97
- location: loc !== '' && loc !== '\n' ? loc : '',
97
+ location: loc?.trim() ?? '',
98
98
  })
99
99
  }
100
100
 
package/rr/hinfo.js CHANGED
@@ -39,26 +39,29 @@ export default class HINFO extends RR {
39
39
  }
40
40
 
41
41
  /****** IMPORTERS *******/
42
- fromBind(opts) {
42
+ fromBind({ bindline }) {
43
43
  // test.example.com 3600 IN HINFO DEC-2060 TOPS20
44
- const regex = /^([\S]+)\s+([0-9]{1,10})\s+(IN)\s+(HINFO)\s+("[^"]+"|[\S]+)\s+("[^"]+"|[\S]+)/i
45
- const match = opts.bindline.trim().match(regex)
46
- if (!match) this.throwHelp(`unable to parse HINFO: ${opts.bindline}`)
47
- const [owner, ttl, c, type, cpu, os] = match.slice(1)
44
+ const regex =
45
+ /^(?<owner>\S+)\s+(?<ttl>\d{1,10})\s+(?<class>IN)\s+(?<type>HINFO)\s+(?:"(?<qCPU>[^"]*)"|(?<uCPU>\S+))\s+(?:"(?<qOS>[^"]*)"|(?<uOS>\S+))$/i
46
+
47
+ const match = bindline.trim().match(regex)
48
+ if (!match) this.throwHelp(`unable to parse HINFO: ${bindline}`)
49
+
50
+ const { owner, ttl, class: c, type, qCPU, uCPU, qOS, uOS } = match.groups
48
51
 
49
52
  return new HINFO({
50
53
  owner,
51
54
  ttl: parseInt(ttl, 10),
52
55
  class: c,
53
56
  type,
54
- cpu,
55
- os,
57
+ cpu: qCPU ?? uCPU,
58
+ os: qOS ?? uOS,
56
59
  })
57
60
  }
58
61
 
59
- fromTinydns(opts) {
62
+ fromTinydns({ tinyline }) {
60
63
  // HINFO via generic, :fqdn:n:rdata:ttl:timestamp:lo
61
- const [fqdn, , rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
64
+ const [fqdn, , rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
62
65
  const [cpu, os] = [...TINYDNS.unpackString(rdata)]
63
66
 
64
67
  return new this.constructor({
@@ -68,7 +71,7 @@ export default class HINFO extends RR {
68
71
  cpu,
69
72
  os,
70
73
  timestamp: ts,
71
- location: loc !== '' && loc !== '\n' ? loc : '',
74
+ location: loc?.trim() ?? '',
72
75
  })
73
76
  }
74
77
 
package/rr/hip.js CHANGED
@@ -59,9 +59,50 @@ export default class HIP extends RR {
59
59
  }
60
60
 
61
61
  /****** IMPORTERS *******/
62
- fromBind(opts) {
62
+ fromTinydns({ tinyline }) {
63
+ // HIP via generic, :fqdn:55:rdata:ttl:timestamp:lo
64
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
65
+ if (n != 55) this.throwHelp('HIP fromTinydns, invalid n')
66
+
67
+ const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
68
+ const hitLen = bytes.readUInt8(0)
69
+ const pkAlgorithm = bytes.readUInt8(1)
70
+ const pkLen = bytes.readUInt16BE(2)
71
+
72
+ const hit = bytes
73
+ .slice(4, 4 + hitLen)
74
+ .toString('hex')
75
+ .toUpperCase()
76
+ const publicKey = bytes.slice(4 + hitLen, 4 + hitLen + pkLen).toString('base64')
77
+
78
+ const rvsNames = []
79
+ let pos = 4 + hitLen + pkLen
80
+ while (pos < bytes.length) {
81
+ const [name, newPos] = TINYDNS.unpackDomainName(
82
+ [...bytes.slice(pos)]
83
+ .map((b) => (b < 32 || b > 126 ? TINYDNS.UInt8toOctal(b) : String.fromCharCode(b)))
84
+ .join(''),
85
+ )
86
+ pos += newPos
87
+ if (name !== '.') rvsNames.push(name)
88
+ }
89
+
90
+ return new HIP({
91
+ owner: this.fullyQualify(fqdn),
92
+ ttl: parseInt(ttl, 10),
93
+ type: 'HIP',
94
+ 'pk algorithm': pkAlgorithm,
95
+ hit,
96
+ 'public key': publicKey,
97
+ 'rendezvous servers': rvsNames.join(' '),
98
+ timestamp: ts,
99
+ location: loc?.trim() ?? '',
100
+ })
101
+ }
102
+
103
+ fromBind({ bindline }) {
63
104
  // owner ttl IN HIP pk-algorithm HIT public-key [rendezvous-server...]
64
- const parts = opts.bindline.split(/\s+/)
105
+ const parts = bindline.split(/\s+/)
65
106
  const [owner, ttl, c, type, pkAlgorithm, hit, publicKey] = parts
66
107
  return new HIP({
67
108
  owner,
package/rr/https.js CHANGED
@@ -46,9 +46,9 @@ export default class HTTPS extends RR {
46
46
 
47
47
  /****** IMPORTERS *******/
48
48
 
49
- fromBind(opts) {
49
+ fromBind({ bindline }) {
50
50
  // test.example.com 3600 IN HTTPS Priority TargetName Params
51
- const [owner, ttl, c, type, pri, fqdn] = opts.bindline.split(/\s+/)
51
+ const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\s+/)
52
52
  return new HTTPS({
53
53
  owner,
54
54
  ttl: parseInt(ttl, 10),
@@ -56,7 +56,41 @@ export default class HTTPS extends RR {
56
56
  type,
57
57
  priority: parseInt(pri, 10),
58
58
  'target name': fqdn,
59
- params: opts.bindline.split(/\s+/).slice(6).join(' ').trim(),
59
+ params: bindline.split(/\s+/).slice(6).join(' ').trim(),
60
+ })
61
+ }
62
+
63
+ fromTinydns({ tinyline }) {
64
+ const [owner, _typeId, rd, ttl, ts, loc] = tinyline.slice(1).split(':')
65
+
66
+ if (rd.length < 6) {
67
+ this.throwHelp(`HTTPS: RDATA too short: ${rd}`)
68
+ }
69
+
70
+ const binary = Buffer.from(TINYDNS.octalToChar(rd), 'binary')
71
+ const priority = binary.readUInt16BE(0)
72
+
73
+ let pos = 2
74
+ const labels = []
75
+ while (true) {
76
+ const len = binary.readUInt8(pos)
77
+ pos += 1
78
+ if (len === 0) break
79
+ labels.push(binary.slice(pos, pos + len).toString())
80
+ pos += len
81
+ }
82
+ const targetName = `${labels.join('.')}.`
83
+ const params = binary.slice(pos).toString()
84
+
85
+ return new HTTPS({
86
+ owner: this.fullyQualify(owner),
87
+ ttl: parseInt(ttl, 10),
88
+ type: 'HTTPS',
89
+ priority,
90
+ 'target name': targetName,
91
+ params,
92
+ timestamp: ts,
93
+ location: loc?.trim() ?? '',
60
94
  })
61
95
  }
62
96
 
package/rr/ipseckey.js CHANGED
@@ -98,9 +98,9 @@ export default class IPSECKEY extends RR {
98
98
  }
99
99
 
100
100
  /****** IMPORTERS *******/
101
- fromBind(opts) {
101
+ fromBind({ bindline }) {
102
102
  // FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey
103
- const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] = opts.bindline.split(/\s+/)
103
+ const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] = bindline.split(/\s+/)
104
104
  return new IPSECKEY({
105
105
  owner,
106
106
  ttl: parseInt(ttl, 10),
@@ -114,32 +114,32 @@ export default class IPSECKEY extends RR {
114
114
  })
115
115
  }
116
116
 
117
- fromTinydns(opts) {
118
- const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
117
+ fromTinydns({ tinyline }) {
118
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
119
119
  if (n != 45) this.throwHelp('IPSECKEY fromTinydns, invalid n')
120
120
 
121
- const precedence = TINYDNS.octalToUInt8(rdata.substring(0, 4))
122
- const gwType = TINYDNS.octalToUInt8(rdata.substring(4, 8))
123
- const algorithm = TINYDNS.octalToUInt8(rdata.substring(8, 12))
121
+ const precedence = TINYDNS.octalToUInt8(rdata.slice(0, 4))
122
+ const gwType = TINYDNS.octalToUInt8(rdata.slice(4, 8))
123
+ const algorithm = TINYDNS.octalToUInt8(rdata.slice(8, 12))
124
124
 
125
125
  let len, gateway, octalKey
126
126
 
127
127
  switch (gwType) {
128
128
  case 0: // no gateway
129
- gateway = rdata.substring(12, 13) // should always be: '.'
130
- octalKey = rdata.substring(13)
129
+ gateway = rdata.slice(12, 13) // should always be: '.'
130
+ octalKey = rdata.slice(13)
131
131
  break
132
132
  case 1: // 4-byte IPv4 address
133
- gateway = TINYDNS.octalToIPv4(rdata.substring(12, 28))
134
- octalKey = rdata.substring(28)
133
+ gateway = TINYDNS.octalToIPv4(rdata.slice(12, 28))
134
+ octalKey = rdata.slice(28)
135
135
  break
136
136
  case 2: // 16-byte IPv6
137
- gateway = TINYDNS.octalToHex(rdata.substring(12, 76))
138
- octalKey = rdata.substring(76)
137
+ gateway = TINYDNS.octalToHex(rdata.slice(12, 76))
138
+ octalKey = rdata.slice(76)
139
139
  break
140
140
  case 3: // wire encoded domain name
141
- ;[gateway, len] = TINYDNS.unpackDomainName(rdata.substring(12))
142
- octalKey = rdata.substring(12 + len)
141
+ ;[gateway, len] = TINYDNS.unpackDomainName(rdata.slice(12))
142
+ octalKey = rdata.slice(12 + len)
143
143
  break
144
144
  }
145
145
 
@@ -153,7 +153,7 @@ export default class IPSECKEY extends RR {
153
153
  gateway,
154
154
  publickey: TINYDNS.octalToBase64(octalKey),
155
155
  timestamp: ts,
156
- location: loc !== '' && loc !== '\n' ? loc : '',
156
+ location: loc?.trim() ?? '',
157
157
  })
158
158
  }
159
159
 
package/rr/key.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import RR from '../rr.js'
2
+ import * as TINYDNS from '../lib/tinydns.js'
2
3
 
3
4
  export default class KEY extends RR {
4
5
  constructor(opts) {
@@ -64,9 +65,9 @@ export default class KEY extends RR {
64
65
 
65
66
  /****** IMPORTERS *******/
66
67
 
67
- fromBind(opts) {
68
+ fromBind({ bindline }) {
68
69
  // test.example.com 3600 IN KEY Flags Protocol Algorithm PublicKey
69
- const [owner, ttl, c, type, flags, protocol, algorithm] = opts.bindline.split(/\s+/)
70
+ const [owner, ttl, c, type, flags, protocol, algorithm] = bindline.split(/\s+/)
70
71
  return new KEY({
71
72
  owner,
72
73
  ttl: parseInt(ttl, 10),
@@ -75,9 +76,39 @@ export default class KEY extends RR {
75
76
  flags: parseInt(flags, 10),
76
77
  protocol: parseInt(protocol, 10),
77
78
  algorithm: parseInt(algorithm, 10),
78
- publickey: opts.bindline.split(/\s+/).slice(7).join(' ').trim(),
79
+ publickey: bindline.split(/\s+/).slice(7).join(' ').trim(),
80
+ })
81
+ }
82
+
83
+ fromTinydns({ tinyline }) {
84
+ // RDATA format: Flags (6 octal chars) + Protocol (3 octal chars) + Algorithm (3 octal chars) + Public Key (escaped data)
85
+ const [owner, _typeId, rd, ttl, ts, loc] = tinyline.slice(1).split(':')
86
+ if (rd.length < 12) {
87
+ this.throwHelp(`KEY: RDATA too short: ${rd}`)
88
+ }
89
+
90
+ return new KEY({
91
+ owner: this.fullyQualify(owner),
92
+ ttl: parseInt(ttl, 10),
93
+ type: 'KEY',
94
+ flags: TINYDNS.octalToUInt16(rd.slice(0, 6)),
95
+ protocol: TINYDNS.octalToUInt8(rd.slice(6, 9)),
96
+ algorithm: TINYDNS.octalToUInt8(rd.slice(9, 12)),
97
+ publickey: TINYDNS.unescapeOctal(rd.slice(12)),
98
+ timestamp: ts,
99
+ location: loc?.trim() ?? '',
79
100
  })
80
101
  }
81
102
 
82
103
  /****** EXPORTERS *******/
104
+ toTinydns() {
105
+ const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
106
+
107
+ return this.getTinydnsGeneric(
108
+ TINYDNS.UInt16toOctal(this.get('flags')) +
109
+ TINYDNS.UInt8toOctal(this.get('protocol')) +
110
+ TINYDNS.UInt8toOctal(this.get('algorithm')) +
111
+ TINYDNS.escapeOctal(dataRe, this.get('publickey')),
112
+ )
113
+ }
83
114
  }
package/rr/kx.js CHANGED
@@ -51,9 +51,25 @@ export default class KX extends RR {
51
51
  }
52
52
 
53
53
  /****** IMPORTERS *******/
54
- fromBind(opts) {
54
+ fromTinydns({ tinyline }) {
55
+ // KX via generic, :fqdn:36:rdata:ttl:timestamp:lo
56
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
57
+ if (n != 36) this.throwHelp('KX fromTinydns, invalid n')
58
+
59
+ return new KX({
60
+ owner: this.fullyQualify(fqdn),
61
+ ttl: parseInt(ttl, 10),
62
+ type: 'KX',
63
+ preference: TINYDNS.octalToUInt16(rdata.slice(0, 8)),
64
+ exchanger: TINYDNS.unpackDomainName(rdata.slice(8))[0],
65
+ timestamp: ts,
66
+ location: loc?.trim() ?? '',
67
+ })
68
+ }
69
+
70
+ fromBind({ bindline }) {
55
71
  // test.example.com 3600 IN KX preference exchanger
56
- const [owner, ttl, c, type, preference, exchanger] = opts.bindline.split(/\s+/)
72
+ const [owner, ttl, c, type, preference, exchanger] = bindline.split(/\s+/)
57
73
  return new KX({
58
74
  owner,
59
75
  ttl: parseInt(ttl, 10),
package/rr/loc.js CHANGED
@@ -85,22 +85,22 @@ export default class LOC extends RR {
85
85
  }
86
86
 
87
87
  /****** IMPORTERS *******/
88
- fromTinydns(opts) {
88
+ fromTinydns({ tinyline }) {
89
89
  // LOC via generic, :fqdn:n:rdata:ttl:timestamp:lo
90
- const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
90
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
91
91
  if (n != 29) this.throwHelp('LOC fromTinydns, invalid n')
92
92
 
93
93
  // divide by 100 is to convert cm to meters
94
94
  const l = {
95
- version: TINYDNS.octalToUInt8(rdata.substring(0, 4)),
96
- size: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(4, 8))),
95
+ version: TINYDNS.octalToUInt8(rdata.slice(0, 4)),
96
+ size: this.fromExponent(TINYDNS.octalToUInt8(rdata.slice(4, 8))),
97
97
  precision: {
98
- horizontal: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(8, 12))),
99
- vertical: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(12, 16))),
98
+ horizontal: this.fromExponent(TINYDNS.octalToUInt8(rdata.slice(8, 12))),
99
+ vertical: this.fromExponent(TINYDNS.octalToUInt8(rdata.slice(12, 16))),
100
100
  },
101
- latitude: this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.substring(16, 32)), 'lat'),
102
- longitude: this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.substring(32, 48)), 'lon'),
103
- altitude: TINYDNS.octalToUInt32(rdata.substring(48, 64)) - REF.ALTITUDE,
101
+ latitude: this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.slice(16, 32)), 'lat'),
102
+ longitude: this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.slice(32, 48)), 'lon'),
103
+ altitude: TINYDNS.octalToUInt32(rdata.slice(48, 64)) - REF.ALTITUDE,
104
104
  }
105
105
 
106
106
  return new LOC({
@@ -109,24 +109,24 @@ export default class LOC extends RR {
109
109
  address: this.toHuman(l),
110
110
  ttl: parseInt(ttl, 10),
111
111
  timestamp: ts,
112
- location: loc !== '' && loc !== '\n' ? loc : '',
112
+ location: loc?.trim() ?? '',
113
113
  })
114
114
  }
115
115
 
116
- fromBind(opts) {
117
- const [owner, ttl, c, type] = opts.bindline.split(/\s+/)
116
+ fromBind({ bindline }) {
117
+ const [owner, ttl, c, type] = bindline.split(/\s+/)
118
118
 
119
119
  return new LOC({
120
120
  owner,
121
121
  ttl: parseInt(ttl, 10),
122
122
  class: c,
123
123
  type: type,
124
- address: opts.bindline.split(/\s+/).slice(4).join(' ').trim(),
124
+ address: bindline.split(/\s+/).slice(4).join(' ').trim(),
125
125
  })
126
126
  }
127
127
 
128
128
  dmsToArcSec(obj) {
129
- let retval = obj.degrees * CONV.deg + (obj.minutes || 0) * CONV.min + (obj.seconds || 0) * CONV.sec
129
+ let retval = obj.degrees * CONV.deg + (obj.minutes ?? 0) * CONV.min + (obj.seconds ?? 0) * CONV.sec
130
130
  switch (obj.hemisphere.toUpperCase()) {
131
131
  case 'W':
132
132
  case 'S':
package/rr/mx.js CHANGED
@@ -53,10 +53,10 @@ export default class MX extends RR {
53
53
  }
54
54
 
55
55
  /****** IMPORTERS *******/
56
- fromTinydns(opts) {
56
+ fromTinydns({ tinyline }) {
57
57
  // @fqdn:ip:x:dist:ttl:timestamp:lo
58
58
  // eslint-disable-next-line no-unused-vars
59
- const [owner, ip, x, preference, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
59
+ const [owner, ip, x, preference, ttl, ts, loc] = tinyline.slice(1).split(':')
60
60
 
61
61
  return new MX({
62
62
  type: 'MX',
@@ -65,13 +65,13 @@ export default class MX extends RR {
65
65
  preference: parseInt(preference, 10) || 0,
66
66
  ttl: parseInt(ttl, 10),
67
67
  timestamp: ts,
68
- location: loc !== '' && loc !== '\n' ? loc : '',
68
+ location: loc?.trim() ?? '',
69
69
  })
70
70
  }
71
71
 
72
- fromBind(opts) {
72
+ fromBind({ bindline }) {
73
73
  // test.example.com 3600 IN MX preference exchange
74
- const [owner, ttl, c, type, preference, exchange] = opts.bindline.split(/\s+/)
74
+ const [owner, ttl, c, type, preference, exchange] = bindline.split(/\s+/)
75
75
 
76
76
  return new MX({
77
77
  owner,
package/rr/naptr.js CHANGED
@@ -62,9 +62,9 @@ export default class NAPTR extends RR {
62
62
  }
63
63
 
64
64
  /****** IMPORTERS *******/
65
- fromTinydns(opts) {
65
+ fromTinydns({ tinyline }) {
66
66
  // NAPTR via generic, :fqdn:n:rdata:ttl:timestamp:lo
67
- const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
67
+ const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
68
68
  if (n != 35) this.throwHelp('NAPTR fromTinydns, invalid n')
69
69
 
70
70
  const binRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
@@ -74,7 +74,7 @@ export default class NAPTR extends RR {
74
74
  owner: this.fullyQualify(fqdn),
75
75
  ttl: parseInt(ttl, 10),
76
76
  timestamp: ts,
77
- location: loc !== '' && loc !== '\n' ? loc : '',
77
+ location: loc?.trim() ?? '',
78
78
  order: binRdata.readUInt16BE(0, 2),
79
79
  preference: binRdata.readUInt16BE(2, 4),
80
80
  }
@@ -82,7 +82,7 @@ export default class NAPTR extends RR {
82
82
  let idx = 4
83
83
  const flagsLength = binRdata.readUInt8(idx)
84
84
  idx++
85
- rec.flags = binRdata.slice(idx, flagsLength).toString()
85
+ rec.flags = binRdata.slice(idx, idx + flagsLength).toString()
86
86
  idx += flagsLength
87
87
 
88
88
  const serviceLen = binRdata.readUInt8(idx)
@@ -102,26 +102,30 @@ export default class NAPTR extends RR {
102
102
  return new NAPTR(rec)
103
103
  }
104
104
 
105
- fromBind(opts) {
106
- const str = opts.bindline
107
- // test.example.com 3600 IN NAPTR order, preference, "flags", "service", "regexp", replacement
108
- const [owner, ttl, c, type, order, preference] = str.split(/\s+/)
109
- const [flags, service, regexp] = str.match(/(?:").*?(?:"\s)/g)
110
- const replacement = str.trim().split(/\s+/).pop()
105
+ fromBind({ bindline }) {
106
+ const regex =
107
+ /^(?<owner>\S+)\s+(?<ttl>\d+)\s+(?<class>\S+)\s+(?<type>NAPTR)\s+(?<order>\d+)\s+(?<preference>\d+)\s+["'](?<flags>[^"']*)["']\s+["'](?<service>[^"']*)["']\s+["'](?<regexp>[^"']*)["']\s+(?<replacement>\S+)$/
111
108
 
112
- const bits = {
113
- owner: owner,
109
+ const match = bindline.trim().match(regex)
110
+
111
+ if (!match) {
112
+ throw new Error(`Invalid NAPTR BIND line: ${bindline}`)
113
+ }
114
+
115
+ const { owner, ttl, type, order, preference, flags, service, regexp, replacement } = match.groups
116
+
117
+ return new NAPTR({
118
+ owner: this.fullyQualify(owner),
114
119
  ttl: parseInt(ttl, 10),
115
- class: c,
116
- type: type,
120
+ class: match.groups.class,
121
+ type,
117
122
  order: parseInt(order, 10),
118
123
  preference: parseInt(preference, 10),
119
- flags: flags.trim().replace(/^['"]|['"]$/g, ''),
120
- service: service.trim().replace(/^['"]|['"]$/g, ''),
121
- regexp: regexp.trim().replace(/^['"]|['"]/g, ''),
122
- replacement: replacement,
123
- }
124
- return new NAPTR(bits)
124
+ flags,
125
+ service,
126
+ regexp,
127
+ replacement,
128
+ })
125
129
  }
126
130
 
127
131
  /****** EXPORTERS *******/
package/rr/ns.js CHANGED
@@ -34,10 +34,10 @@ export default class NS extends RR {
34
34
  }
35
35
 
36
36
  /****** IMPORTERS *******/
37
- fromTinydns(opts) {
37
+ fromTinydns({ tinyline }) {
38
38
  // &fqdn:ip:x:ttl:timestamp:lo
39
39
  // eslint-disable-next-line no-unused-vars
40
- const [fqdn, ip, dname, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
40
+ const [fqdn, ip, dname, ttl, ts, loc] = tinyline.slice(1).split(':')
41
41
 
42
42
  return new NS({
43
43
  type: 'NS',
@@ -45,13 +45,13 @@ export default class NS extends RR {
45
45
  dname: this.fullyQualify(/\./.test(dname) ? dname : `${dname}.ns.${fqdn}`),
46
46
  ttl: parseInt(ttl, 10),
47
47
  timestamp: ts,
48
- location: loc !== '' && loc !== '\n' ? loc : '',
48
+ location: loc?.trim() ?? '',
49
49
  })
50
50
  }
51
51
 
52
- fromBind(opts) {
52
+ fromBind({ bindline }) {
53
53
  // test.example.com 3600 IN NS dname
54
- const [owner, ttl, c, type, dname] = opts.bindline.split(/\s+/)
54
+ const [owner, ttl, c, type, dname] = bindline.split(/\s+/)
55
55
 
56
56
  return new NS({
57
57
  owner,
package/rr/nsec.js CHANGED
@@ -43,16 +43,32 @@ export default class NSEC extends RR {
43
43
 
44
44
  /****** IMPORTERS *******/
45
45
 
46
- fromBind(opts) {
46
+ fromTinydns({ tinyline }) {
47
+ const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
48
+ const binaryRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
49
+ const [nextDomain, _escapedLen, binaryLen] = TINYDNS.unpackDomainName(rdata)
50
+
51
+ return new NSEC({
52
+ owner: this.fullyQualify(owner),
53
+ ttl: parseInt(ttl, 10),
54
+ type: 'NSEC',
55
+ 'next domain': nextDomain,
56
+ 'type bit maps': binaryRdata.slice(binaryLen).toString(),
57
+ timestamp: ts,
58
+ location: loc?.trim() ?? '',
59
+ })
60
+ }
61
+
62
+ fromBind({ bindline }) {
47
63
  // test.example.com 3600 IN NSEC NextDomain TypeBitMaps
48
- const [owner, ttl, c, type, next] = opts.bindline.split(/\s+/)
64
+ const [owner, ttl, c, type, next] = bindline.split(/\s+/)
49
65
  return new NSEC({
50
66
  owner,
51
67
  ttl: parseInt(ttl, 10),
52
68
  class: c,
53
69
  type: type,
54
70
  'next domain': next,
55
- 'type bit maps': opts.bindline.split(/\s+/).slice(5).filter(removeParens).join(' ').trim(),
71
+ 'type bit maps': bindline.split(/\s+/).slice(5).filter(removeParens).join(' ').trim(),
56
72
  })
57
73
  }
58
74