dns2 1.5.0 → 2.0.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.
- package/.eslintrc +16 -0
- package/.github/FUNDING.yml +12 -0
- package/.github/workflows/lint.js.yml +17 -0
- package/.github/workflows/node.js.yml +1 -2
- package/README.md +46 -15
- package/client/doh.js +24 -16
- package/client/google.js +4 -4
- package/client/tcp.js +10 -10
- package/client/udp.js +6 -6
- package/example/client/doh.js +5 -5
- package/example/client/google.js +1 -2
- package/example/client/tcp-custom-dns.js +4 -4
- package/example/client/tcp.js +4 -4
- package/example/client/udp-custom-dns.js +4 -4
- package/example/client/udp-default.js +2 -2
- package/example/client/udp-subnet.js +2 -2
- package/example/client/udp.js +3 -3
- package/example/server/dns.js +46 -0
- package/example/server/doh.js +18 -16
- package/example/server/tcp.js +6 -6
- package/example/server/udp.js +4 -4
- package/index.js +22 -14
- package/lib/reader.js +20 -22
- package/lib/writer.js +11 -11
- package/package.json +11 -3
- package/packet.js +217 -202
- package/server/dns.js +94 -0
- package/server/doh.js +130 -127
- package/server/index.js +10 -3
- package/server/tcp.js +14 -6
- package/server/udp.js +10 -4
- package/test/index.js +255 -104
- package/test/test.js +24 -17
- package/.travis.yml +0 -4
package/packet.js
CHANGED
|
@@ -17,32 +17,32 @@ const debug = debuglog('dns2');
|
|
|
17
17
|
* <-W--W--W-----Z-----C--N>|<----------->|
|
|
18
18
|
*/
|
|
19
19
|
function Packet(data) {
|
|
20
|
-
this.header
|
|
21
|
-
this.questions
|
|
22
|
-
this.answers
|
|
20
|
+
this.header = {};
|
|
21
|
+
this.questions = [];
|
|
22
|
+
this.answers = [];
|
|
23
23
|
this.authorities = [];
|
|
24
24
|
this.additionals = [];
|
|
25
|
-
if(data instanceof Packet) {
|
|
25
|
+
if (data instanceof Packet) {
|
|
26
26
|
return data;
|
|
27
|
-
} else if(data instanceof Packet.Header) {
|
|
27
|
+
} else if (data instanceof Packet.Header) {
|
|
28
28
|
this.header = data;
|
|
29
|
-
} else if(data instanceof Packet.Question) {
|
|
29
|
+
} else if (data instanceof Packet.Question) {
|
|
30
30
|
this.questions.push(data);
|
|
31
|
-
} else if(data instanceof Packet.Resource) {
|
|
31
|
+
} else if (data instanceof Packet.Resource) {
|
|
32
32
|
this.answers.push(data);
|
|
33
|
-
} else if(typeof data === 'string') {
|
|
33
|
+
} else if (typeof data === 'string') {
|
|
34
34
|
this.questions.push(data);
|
|
35
|
-
} else if(typeof data === 'object') {
|
|
36
|
-
|
|
37
|
-
if(type === 'Array') {
|
|
35
|
+
} else if (typeof data === 'object') {
|
|
36
|
+
const type = ({}).toString.call(data).match(/\[object (\w+)\]/)[1];
|
|
37
|
+
if (type === 'Array') {
|
|
38
38
|
this.questions = data;
|
|
39
39
|
}
|
|
40
|
-
if(type === 'Object') {
|
|
40
|
+
if (type === 'Object') {
|
|
41
41
|
this.header = data;
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
return this;
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* [QUERY_TYPE description]
|
|
@@ -82,11 +82,11 @@ Packet.TYPE = {
|
|
|
82
82
|
* @docs https://tools.ietf.org/html/rfc1035#section-3.2.4
|
|
83
83
|
*/
|
|
84
84
|
Packet.CLASS = {
|
|
85
|
-
IN
|
|
86
|
-
CS
|
|
87
|
-
CH
|
|
88
|
-
HS
|
|
89
|
-
ANY: 0xFF
|
|
85
|
+
IN : 0x01,
|
|
86
|
+
CS : 0x02,
|
|
87
|
+
CH : 0x03,
|
|
88
|
+
HS : 0x04,
|
|
89
|
+
ANY : 0xFF,
|
|
90
90
|
};
|
|
91
91
|
/**
|
|
92
92
|
* [EDNS_OPTION_CODE description]
|
|
@@ -94,7 +94,7 @@ Packet.CLASS = {
|
|
|
94
94
|
* @docs https://tools.ietf.org/html/rfc6891#section-6.1.2
|
|
95
95
|
*/
|
|
96
96
|
Packet.EDNS_OPTION_CODE = {
|
|
97
|
-
ECS: 0x08
|
|
97
|
+
ECS: 0x08,
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
/**
|
|
@@ -115,19 +115,19 @@ Packet.parse = function(buffer) {
|
|
|
115
115
|
const reader = new Packet.Reader(buffer);
|
|
116
116
|
packet.header = Packet.Header.parse(reader);
|
|
117
117
|
([ // props parser count
|
|
118
|
-
[ 'questions'
|
|
119
|
-
[ 'answers'
|
|
120
|
-
[ 'authorities'
|
|
121
|
-
[ 'additionals'
|
|
118
|
+
[ 'questions', Packet.Question, packet.header.qdcount ],
|
|
119
|
+
[ 'answers', Packet.Resource, packet.header.ancount ],
|
|
120
|
+
[ 'authorities', Packet.Resource, packet.header.nscount ],
|
|
121
|
+
[ 'additionals', Packet.Resource, packet.header.arcount ],
|
|
122
122
|
]).forEach(function(def) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
while(count--) {
|
|
123
|
+
const section = def[0];
|
|
124
|
+
const decoder = def[1];
|
|
125
|
+
let count = def[2];
|
|
126
|
+
while (count--) {
|
|
127
127
|
try {
|
|
128
|
-
packet[
|
|
129
|
-
packet[
|
|
130
|
-
} catch(e) {
|
|
128
|
+
packet[section] = packet[section] || [];
|
|
129
|
+
packet[section].push(decoder.parse(reader));
|
|
130
|
+
} catch (e) {
|
|
131
131
|
debug('node-dns > parse %s error:', section, e.message);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -135,28 +135,42 @@ Packet.parse = function(buffer) {
|
|
|
135
135
|
return packet;
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
+
/**
|
|
139
|
+
* recursive
|
|
140
|
+
*/
|
|
141
|
+
Object.defineProperty(Packet.prototype, 'recursive', {
|
|
142
|
+
enumerable : true,
|
|
143
|
+
configurable : true,
|
|
144
|
+
get() {
|
|
145
|
+
return !!this.header.rd;
|
|
146
|
+
},
|
|
147
|
+
set(yn) {
|
|
148
|
+
this.header.rd = +yn;
|
|
149
|
+
return this.header.rd;
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
138
153
|
/**
|
|
139
154
|
* [toBuffer description]
|
|
140
155
|
* @return {[type]} [description]
|
|
141
156
|
*/
|
|
142
157
|
Packet.prototype.toBuffer = function(writer) {
|
|
143
158
|
writer = writer || new Packet.Writer();
|
|
144
|
-
this.header.qdcount = this.questions
|
|
145
|
-
this.header.ancount = this.answers
|
|
159
|
+
this.header.qdcount = this.questions.length;
|
|
160
|
+
this.header.ancount = this.answers.length;
|
|
146
161
|
this.header.nscount = this.authorities.length;
|
|
147
162
|
this.header.arcount = this.additionals.length;
|
|
148
|
-
if(!(this instanceof Packet.Header))
|
|
149
|
-
this.header = new Packet.Header(this.header);
|
|
163
|
+
if (!(this instanceof Packet.Header)) { this.header = new Packet.Header(this.header); }
|
|
150
164
|
this.header.toBuffer(writer);
|
|
151
|
-
|
|
152
|
-
[ 'questions'
|
|
153
|
-
[ 'answers'
|
|
165
|
+
([ // section encoder
|
|
166
|
+
[ 'questions', Packet.Question ],
|
|
167
|
+
[ 'answers', Packet.Resource ],
|
|
154
168
|
[ 'authorities', Packet.Resource ],
|
|
155
169
|
[ 'additionals', Packet.Resource ],
|
|
156
170
|
]).forEach(function(def) {
|
|
157
|
-
const section
|
|
158
|
-
const Encoder
|
|
159
|
-
(this[
|
|
171
|
+
const section = def[0];
|
|
172
|
+
const Encoder = def[1];
|
|
173
|
+
(this[section] || []).map(function(resource) {
|
|
160
174
|
return Encoder.encode(resource, writer);
|
|
161
175
|
});
|
|
162
176
|
}.bind(this));
|
|
@@ -169,20 +183,20 @@ Packet.prototype.toBuffer = function(writer) {
|
|
|
169
183
|
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.1
|
|
170
184
|
*/
|
|
171
185
|
Packet.Header = function(header) {
|
|
172
|
-
this.id
|
|
173
|
-
this.qr
|
|
174
|
-
this.opcode
|
|
175
|
-
this.aa
|
|
176
|
-
this.tc
|
|
177
|
-
this.rd
|
|
178
|
-
this.ra
|
|
179
|
-
this.z
|
|
180
|
-
this.rcode
|
|
186
|
+
this.id = 0;
|
|
187
|
+
this.qr = 0;
|
|
188
|
+
this.opcode = 0;
|
|
189
|
+
this.aa = 0;
|
|
190
|
+
this.tc = 0;
|
|
191
|
+
this.rd = 0;
|
|
192
|
+
this.ra = 0;
|
|
193
|
+
this.z = 0;
|
|
194
|
+
this.rcode = 0;
|
|
181
195
|
this.qdcount = 0;
|
|
182
196
|
this.nscount = 0;
|
|
183
197
|
this.arcount = 0;
|
|
184
|
-
for(
|
|
185
|
-
this[
|
|
198
|
+
for (const k in header) {
|
|
199
|
+
this[k] = header[k];
|
|
186
200
|
}
|
|
187
201
|
return this;
|
|
188
202
|
};
|
|
@@ -193,19 +207,19 @@ Packet.Header = function(header) {
|
|
|
193
207
|
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.1
|
|
194
208
|
*/
|
|
195
209
|
Packet.Header.parse = function(reader) {
|
|
196
|
-
|
|
197
|
-
if(reader instanceof Buffer) {
|
|
210
|
+
const header = new Packet.Header();
|
|
211
|
+
if (reader instanceof Buffer) {
|
|
198
212
|
reader = new Packet.Reader(reader);
|
|
199
213
|
}
|
|
200
|
-
header.id
|
|
201
|
-
header.qr
|
|
202
|
-
header.opcode
|
|
203
|
-
header.aa
|
|
204
|
-
header.tc
|
|
205
|
-
header.rd
|
|
206
|
-
header.ra
|
|
207
|
-
header.z
|
|
208
|
-
header.rcode
|
|
214
|
+
header.id = reader.read(16);
|
|
215
|
+
header.qr = reader.read(1);
|
|
216
|
+
header.opcode = reader.read(4);
|
|
217
|
+
header.aa = reader.read(1);
|
|
218
|
+
header.tc = reader.read(1);
|
|
219
|
+
header.rd = reader.read(1);
|
|
220
|
+
header.ra = reader.read(1);
|
|
221
|
+
header.z = reader.read(3);
|
|
222
|
+
header.rcode = reader.read(4);
|
|
209
223
|
header.qdcount = reader.read(16);
|
|
210
224
|
header.ancount = reader.read(16);
|
|
211
225
|
header.nscount = reader.read(16);
|
|
@@ -219,19 +233,19 @@ Packet.Header.parse = function(reader) {
|
|
|
219
233
|
*/
|
|
220
234
|
Packet.Header.prototype.toBuffer = function(writer) {
|
|
221
235
|
writer = writer || new Packet.Writer();
|
|
222
|
-
writer.write(this.id
|
|
223
|
-
writer.write(this.qr
|
|
224
|
-
writer.write(this.opcode
|
|
225
|
-
writer.write(this.aa
|
|
226
|
-
writer.write(this.tc
|
|
227
|
-
writer.write(this.rd
|
|
228
|
-
writer.write(this.ra
|
|
229
|
-
writer.write(this.z
|
|
230
|
-
writer.write(this.rcode
|
|
231
|
-
writer.write(this.qdcount, 16)
|
|
232
|
-
writer.write(this.ancount, 16)
|
|
233
|
-
writer.write(this.nscount, 16)
|
|
234
|
-
writer.write(this.arcount, 16)
|
|
236
|
+
writer.write(this.id, 16);
|
|
237
|
+
writer.write(this.qr, 1);
|
|
238
|
+
writer.write(this.opcode, 4);
|
|
239
|
+
writer.write(this.aa, 1);
|
|
240
|
+
writer.write(this.tc, 1);
|
|
241
|
+
writer.write(this.rd, 1);
|
|
242
|
+
writer.write(this.ra, 1);
|
|
243
|
+
writer.write(this.z, 3);
|
|
244
|
+
writer.write(this.rcode, 4);
|
|
245
|
+
writer.write(this.qdcount, 16);
|
|
246
|
+
writer.write(this.ancount, 16);
|
|
247
|
+
writer.write(this.nscount, 16);
|
|
248
|
+
writer.write(this.arcount, 16);
|
|
235
249
|
return writer.toBuffer();
|
|
236
250
|
};
|
|
237
251
|
|
|
@@ -240,13 +254,14 @@ Packet.Header.prototype.toBuffer = function(writer) {
|
|
|
240
254
|
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.2
|
|
241
255
|
*/
|
|
242
256
|
Packet.Question = function(name, type, cls) {
|
|
243
|
-
|
|
244
|
-
type
|
|
245
|
-
class: Packet.CLASS.ANY,
|
|
257
|
+
const defaults = {
|
|
258
|
+
type : Packet.TYPE.ANY,
|
|
259
|
+
class : Packet.CLASS.ANY,
|
|
246
260
|
};
|
|
247
|
-
if(typeof name === 'object') {
|
|
248
|
-
for(
|
|
249
|
-
this[
|
|
261
|
+
if (typeof name === 'object') {
|
|
262
|
+
for (const k in name) {
|
|
263
|
+
this[k] = name[k] || defaults[k];
|
|
264
|
+
}
|
|
250
265
|
} else {
|
|
251
266
|
this.name = name;
|
|
252
267
|
this.type = type || defaults.type;
|
|
@@ -271,20 +286,20 @@ Packet.Question.prototype.toBuffer = function(writer) {
|
|
|
271
286
|
*/
|
|
272
287
|
Packet.Question.parse =
|
|
273
288
|
Packet.Question.decode = function(reader) {
|
|
274
|
-
|
|
275
|
-
if(reader instanceof Buffer) {
|
|
289
|
+
const question = new Packet.Question();
|
|
290
|
+
if (reader instanceof Buffer) {
|
|
276
291
|
reader = new Packet.Reader(reader);
|
|
277
292
|
}
|
|
278
293
|
question.name = Packet.Name.decode(reader);
|
|
279
294
|
question.type = reader.read(16);
|
|
280
|
-
question.class= reader.read(16);
|
|
295
|
+
question.class = reader.read(16);
|
|
281
296
|
return question;
|
|
282
297
|
};
|
|
283
298
|
|
|
284
299
|
Packet.Question.encode = function(question, writer) {
|
|
285
300
|
writer = writer || new Packet.Writer();
|
|
286
301
|
Packet.Name.encode(question.name, writer);
|
|
287
|
-
writer.write(question.type,
|
|
302
|
+
writer.write(question.type, 16);
|
|
288
303
|
writer.write(question.class, 16);
|
|
289
304
|
return writer.toBuffer();
|
|
290
305
|
};
|
|
@@ -294,20 +309,20 @@ Packet.Question.encode = function(question, writer) {
|
|
|
294
309
|
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.3
|
|
295
310
|
*/
|
|
296
311
|
Packet.Resource = function(name, type, cls, ttl) {
|
|
297
|
-
|
|
298
|
-
name
|
|
299
|
-
ttl
|
|
300
|
-
type
|
|
301
|
-
class: Packet.CLASS.ANY,
|
|
312
|
+
const defaults = {
|
|
313
|
+
name : '',
|
|
314
|
+
ttl : 300,
|
|
315
|
+
type : Packet.TYPE.ANY,
|
|
316
|
+
class : Packet.CLASS.ANY,
|
|
302
317
|
};
|
|
303
|
-
|
|
304
|
-
|
|
318
|
+
let input;
|
|
319
|
+
if (typeof name === 'object') {
|
|
305
320
|
input = name;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
321
|
+
} else {
|
|
322
|
+
input = {
|
|
323
|
+
name, type, class: cls, ttl,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
311
326
|
Object.assign(this, defaults, input);
|
|
312
327
|
return this;
|
|
313
328
|
};
|
|
@@ -330,14 +345,14 @@ Packet.Resource.prototype.toBuffer = function(writer) {
|
|
|
330
345
|
Packet.Resource.encode = function(resource, writer) {
|
|
331
346
|
writer = writer || new Packet.Writer();
|
|
332
347
|
Packet.Name.encode(resource.name, writer);
|
|
333
|
-
writer.write(resource.type,
|
|
348
|
+
writer.write(resource.type, 16);
|
|
334
349
|
writer.write(resource.class, 16);
|
|
335
|
-
writer.write(resource.ttl,
|
|
336
|
-
|
|
337
|
-
return resource.type
|
|
350
|
+
writer.write(resource.ttl, 32);
|
|
351
|
+
const encoder = Object.keys(Packet.TYPE).filter(function(type) {
|
|
352
|
+
return resource.type === Packet.TYPE[type];
|
|
338
353
|
})[0];
|
|
339
|
-
if(encoder in Packet.Resource && Packet.Resource[
|
|
340
|
-
return Packet.Resource[
|
|
354
|
+
if (encoder in Packet.Resource && Packet.Resource[encoder].encode) {
|
|
355
|
+
return Packet.Resource[encoder].encode(resource, writer);
|
|
341
356
|
} else {
|
|
342
357
|
debug('node-dns > unknown encoder %s(%j)', encoder, resource.type);
|
|
343
358
|
}
|
|
@@ -349,24 +364,24 @@ Packet.Resource.encode = function(resource, writer) {
|
|
|
349
364
|
*/
|
|
350
365
|
Packet.Resource.parse =
|
|
351
366
|
Packet.Resource.decode = function(reader) {
|
|
352
|
-
if(reader instanceof Buffer) {
|
|
367
|
+
if (reader instanceof Buffer) {
|
|
353
368
|
reader = new Packet.Reader(reader);
|
|
354
369
|
}
|
|
355
|
-
|
|
356
|
-
resource.name
|
|
357
|
-
resource.type
|
|
370
|
+
let resource = new Packet.Resource();
|
|
371
|
+
resource.name = Packet.Name.decode(reader);
|
|
372
|
+
resource.type = reader.read(16);
|
|
358
373
|
resource.class = reader.read(16);
|
|
359
|
-
resource.ttl
|
|
360
|
-
|
|
374
|
+
resource.ttl = reader.read(32);
|
|
375
|
+
let length = reader.read(16);
|
|
361
376
|
const parser = Object.keys(Packet.TYPE).filter(function(type) {
|
|
362
|
-
return resource.type === Packet.TYPE[
|
|
377
|
+
return resource.type === Packet.TYPE[type];
|
|
363
378
|
})[0];
|
|
364
|
-
if(parser in Packet.Resource) {
|
|
365
|
-
resource = Packet.Resource[
|
|
379
|
+
if (parser in Packet.Resource) {
|
|
380
|
+
resource = Packet.Resource[parser].decode.call(resource, reader, length);
|
|
366
381
|
} else {
|
|
367
382
|
debug('node-dns > unknown parser type: %s(%j)', parser, resource.type);
|
|
368
383
|
const arr = [];
|
|
369
|
-
while(length--) arr.push(reader.read(8));
|
|
384
|
+
while (length--) arr.push(reader.read(8));
|
|
370
385
|
resource.data = Buffer.from(arr);
|
|
371
386
|
}
|
|
372
387
|
return resource;
|
|
@@ -378,29 +393,29 @@ Packet.Resource.decode = function(reader) {
|
|
|
378
393
|
* @return {[type]} [description]
|
|
379
394
|
*/
|
|
380
395
|
Packet.Name = {
|
|
381
|
-
COPY: 0xc0,
|
|
382
|
-
decode: function(reader) {
|
|
383
|
-
if(reader instanceof Buffer) {
|
|
396
|
+
COPY : 0xc0,
|
|
397
|
+
decode : function(reader) {
|
|
398
|
+
if (reader instanceof Buffer) {
|
|
384
399
|
reader = new Packet.Reader(reader);
|
|
385
400
|
}
|
|
386
|
-
|
|
387
|
-
while(len) {
|
|
388
|
-
if((len & Packet.Name.COPY) === Packet.Name.COPY) {
|
|
401
|
+
const name = []; let o; let len = reader.read(8);
|
|
402
|
+
while (len) {
|
|
403
|
+
if ((len & Packet.Name.COPY) === Packet.Name.COPY) {
|
|
389
404
|
len -= Packet.Name.COPY;
|
|
390
405
|
len = len << 8;
|
|
391
|
-
|
|
392
|
-
if(!o) o = reader.offset;
|
|
406
|
+
const pos = len + reader.read(8);
|
|
407
|
+
if (!o) o = reader.offset;
|
|
393
408
|
reader.offset = pos * 8;
|
|
394
409
|
len = reader.read(8);
|
|
395
410
|
continue;
|
|
396
411
|
} else {
|
|
397
|
-
|
|
398
|
-
while(len--) part += String.fromCharCode(reader.read(8));
|
|
412
|
+
let part = '';
|
|
413
|
+
while (len--) part += String.fromCharCode(reader.read(8));
|
|
399
414
|
name.push(part);
|
|
400
415
|
len = reader.read(8);
|
|
401
416
|
}
|
|
402
417
|
}
|
|
403
|
-
if(o) reader.offset = o;
|
|
418
|
+
if (o) reader.offset = o;
|
|
404
419
|
return name.join('.');
|
|
405
420
|
},
|
|
406
421
|
encode: function(domain, writer) {
|
|
@@ -408,16 +423,16 @@ Packet.Name = {
|
|
|
408
423
|
// TODO: domain name compress
|
|
409
424
|
(domain || '').split('.').filter(function(part) {
|
|
410
425
|
return !!part;
|
|
411
|
-
}).
|
|
426
|
+
}).forEach(function(part) {
|
|
412
427
|
writer.write(part.length, 8);
|
|
413
428
|
part.split('').map(function(c) {
|
|
414
429
|
writer.write(c.charCodeAt(0), 8);
|
|
415
|
-
return c.charCodeAt(0)
|
|
430
|
+
return c.charCodeAt(0);
|
|
416
431
|
});
|
|
417
432
|
});
|
|
418
433
|
writer.write(0, 8);
|
|
419
434
|
return writer.toBuffer();
|
|
420
|
-
}
|
|
435
|
+
},
|
|
421
436
|
};
|
|
422
437
|
|
|
423
438
|
/**
|
|
@@ -426,7 +441,7 @@ Packet.Name = {
|
|
|
426
441
|
* @docs https://tools.ietf.org/html/rfc1035#section-3.4.1
|
|
427
442
|
*/
|
|
428
443
|
Packet.Resource.A = function(address) {
|
|
429
|
-
this.type
|
|
444
|
+
this.type = Packet.TYPE.A;
|
|
430
445
|
this.class = Packet.CLASS.IN;
|
|
431
446
|
this.address = address;
|
|
432
447
|
return this;
|
|
@@ -434,7 +449,7 @@ Packet.Resource.A = function(address) {
|
|
|
434
449
|
|
|
435
450
|
Packet.Resource.A.encode = function(record, writer) {
|
|
436
451
|
writer = writer || new Packet.Writer();
|
|
437
|
-
|
|
452
|
+
const parts = record.address.split('.');
|
|
438
453
|
writer.write(parts.length, 16);
|
|
439
454
|
parts.forEach(function(part) {
|
|
440
455
|
writer.write(parseInt(part, 10), 8);
|
|
@@ -443,8 +458,8 @@ Packet.Resource.A.encode = function(record, writer) {
|
|
|
443
458
|
};
|
|
444
459
|
|
|
445
460
|
Packet.Resource.A.decode = function(reader, length) {
|
|
446
|
-
|
|
447
|
-
while(length--) parts.push(reader.read(8));
|
|
461
|
+
const parts = [];
|
|
462
|
+
while (length--) parts.push(reader.read(8));
|
|
448
463
|
this.address = parts.join('.');
|
|
449
464
|
return this;
|
|
450
465
|
};
|
|
@@ -461,7 +476,7 @@ Packet.Resource.MX = function(exchange, priority) {
|
|
|
461
476
|
this.exchange = exchange;
|
|
462
477
|
this.priority = priority;
|
|
463
478
|
return this;
|
|
464
|
-
}
|
|
479
|
+
};
|
|
465
480
|
/**
|
|
466
481
|
* [encode description]
|
|
467
482
|
* @param {[type]} record [description]
|
|
@@ -470,12 +485,12 @@ Packet.Resource.MX = function(exchange, priority) {
|
|
|
470
485
|
*/
|
|
471
486
|
Packet.Resource.MX.encode = function(record, writer) {
|
|
472
487
|
writer = writer || new Packet.Writer();
|
|
473
|
-
|
|
488
|
+
const len = Packet.Name.encode(record.exchange).length;
|
|
474
489
|
writer.write(len + 2, 16);
|
|
475
490
|
writer.write(record.priority, 16);
|
|
476
491
|
Packet.Name.encode(record.exchange, writer);
|
|
477
492
|
return writer.toBuffer();
|
|
478
|
-
}
|
|
493
|
+
};
|
|
479
494
|
/**
|
|
480
495
|
* [decode description]
|
|
481
496
|
* @param {[type]} reader [description]
|
|
@@ -494,11 +509,11 @@ Packet.Resource.MX.decode = function(reader, length) {
|
|
|
494
509
|
*/
|
|
495
510
|
Packet.Resource.AAAA = {
|
|
496
511
|
decode: function(reader, length) {
|
|
497
|
-
|
|
498
|
-
while(length) {
|
|
499
|
-
length-=2;
|
|
512
|
+
const parts = [];
|
|
513
|
+
while (length) {
|
|
514
|
+
length -= 2;
|
|
500
515
|
parts.push(reader.read(16));
|
|
501
|
-
}
|
|
516
|
+
}
|
|
502
517
|
this.address = parts.map(function(part) {
|
|
503
518
|
return part > 0 ? part.toString(16) : '';
|
|
504
519
|
}).join(':');
|
|
@@ -506,13 +521,13 @@ Packet.Resource.AAAA = {
|
|
|
506
521
|
},
|
|
507
522
|
encode: function(record, writer) {
|
|
508
523
|
writer = writer || new Packet.Writer();
|
|
509
|
-
|
|
524
|
+
const parts = record.address.split(':');
|
|
510
525
|
writer.write(parts.length * 2, 16);
|
|
511
526
|
parts.forEach(function(part) {
|
|
512
527
|
writer.write(parseInt(part, 16), 16);
|
|
513
528
|
});
|
|
514
529
|
return writer.toBuffer();
|
|
515
|
-
}
|
|
530
|
+
},
|
|
516
531
|
};
|
|
517
532
|
/**
|
|
518
533
|
* [NS description]
|
|
@@ -529,7 +544,7 @@ Packet.Resource.NS = {
|
|
|
529
544
|
writer.write(Packet.Name.encode(record.ns).length, 16);
|
|
530
545
|
Packet.Name.encode(record.ns, writer);
|
|
531
546
|
return writer.toBuffer();
|
|
532
|
-
}
|
|
547
|
+
},
|
|
533
548
|
};
|
|
534
549
|
/**
|
|
535
550
|
* [CNAME description]
|
|
@@ -547,7 +562,7 @@ Packet.Resource.CNAME = {
|
|
|
547
562
|
writer.write(Packet.Name.encode(record.domain).length, 16);
|
|
548
563
|
Packet.Name.encode(record.domain, writer);
|
|
549
564
|
return writer.toBuffer();
|
|
550
|
-
}
|
|
565
|
+
},
|
|
551
566
|
};
|
|
552
567
|
/**
|
|
553
568
|
* [SPF description]
|
|
@@ -557,14 +572,14 @@ Packet.Resource.CNAME = {
|
|
|
557
572
|
Packet.Resource.SPF =
|
|
558
573
|
Packet.Resource.TXT = {
|
|
559
574
|
decode: function(reader, length) {
|
|
560
|
-
|
|
561
|
-
|
|
575
|
+
const parts = [];
|
|
576
|
+
let bytesRead = 0; let chunkLength = 0;
|
|
562
577
|
|
|
563
|
-
while(bytesRead < length) {
|
|
578
|
+
while (bytesRead < length) {
|
|
564
579
|
chunkLength = reader.read(8); // text length
|
|
565
580
|
bytesRead++;
|
|
566
581
|
|
|
567
|
-
while(chunkLength--) {
|
|
582
|
+
while (chunkLength--) {
|
|
568
583
|
parts.push(reader.read(8));
|
|
569
584
|
bytesRead++;
|
|
570
585
|
}
|
|
@@ -577,13 +592,13 @@ Packet.Resource.TXT = {
|
|
|
577
592
|
writer = writer || new Packet.Writer();
|
|
578
593
|
|
|
579
594
|
// make sure that resource data is a an array of strings
|
|
580
|
-
|
|
595
|
+
const characterStrings = Array.isArray(record.data) ? record.data : [ record.data ];
|
|
581
596
|
// convert array of strings to array of buffers
|
|
582
|
-
|
|
583
|
-
if(Buffer.isBuffer(characterString)) {
|
|
597
|
+
const characterStringBuffers = characterStrings.map(function(characterString) {
|
|
598
|
+
if (Buffer.isBuffer(characterString)) {
|
|
584
599
|
return characterString;
|
|
585
600
|
}
|
|
586
|
-
if(typeof characterString === 'string') {
|
|
601
|
+
if (typeof characterString === 'string') {
|
|
587
602
|
return Buffer.from(characterString, 'utf8');
|
|
588
603
|
}
|
|
589
604
|
return false;
|
|
@@ -593,7 +608,7 @@ Packet.Resource.TXT = {
|
|
|
593
608
|
});
|
|
594
609
|
|
|
595
610
|
// calculate byte length of resource strings
|
|
596
|
-
|
|
611
|
+
const bufferLength = characterStringBuffers.reduce(function(sum, characterStringBuffer) {
|
|
597
612
|
return sum + characterStringBuffer.length;
|
|
598
613
|
}, 0);
|
|
599
614
|
|
|
@@ -609,7 +624,7 @@ Packet.Resource.TXT = {
|
|
|
609
624
|
});
|
|
610
625
|
|
|
611
626
|
return writer.toBuffer();
|
|
612
|
-
}
|
|
627
|
+
},
|
|
613
628
|
};
|
|
614
629
|
/**
|
|
615
630
|
* [SOA description]
|
|
@@ -618,31 +633,31 @@ Packet.Resource.TXT = {
|
|
|
618
633
|
*/
|
|
619
634
|
Packet.Resource.SOA = {
|
|
620
635
|
decode: function(reader, length) {
|
|
621
|
-
this.primary
|
|
622
|
-
this.admin
|
|
623
|
-
this.serial
|
|
624
|
-
this.refresh
|
|
625
|
-
this.retry
|
|
636
|
+
this.primary = Packet.Name.decode(reader);
|
|
637
|
+
this.admin = Packet.Name.decode(reader);
|
|
638
|
+
this.serial = reader.read(32);
|
|
639
|
+
this.refresh = reader.read(32);
|
|
640
|
+
this.retry = reader.read(32);
|
|
626
641
|
this.expiration = reader.read(32);
|
|
627
|
-
this.minimum
|
|
642
|
+
this.minimum = reader.read(32);
|
|
628
643
|
return this;
|
|
629
644
|
},
|
|
630
645
|
encode: function(record, writer) {
|
|
631
646
|
writer = writer || new Packet.Writer();
|
|
632
|
-
|
|
647
|
+
let len = 0;
|
|
633
648
|
len += Packet.Name.encode(record.primary).length;
|
|
634
649
|
len += Packet.Name.encode(record.admin).length;
|
|
635
650
|
len += (32 * 5) / 8;
|
|
636
651
|
writer.write(len, 16);
|
|
637
652
|
Packet.Name.encode(record.primary, writer);
|
|
638
653
|
Packet.Name.encode(record.admin, writer);
|
|
639
|
-
writer.write(record.serial
|
|
640
|
-
writer.write(record.refresh
|
|
641
|
-
writer.write(record.retry
|
|
654
|
+
writer.write(record.serial, 32);
|
|
655
|
+
writer.write(record.refresh, 32);
|
|
656
|
+
writer.write(record.retry, 32);
|
|
642
657
|
writer.write(record.expiration, 32);
|
|
643
|
-
writer.write(record.minimum
|
|
658
|
+
writer.write(record.minimum, 32);
|
|
644
659
|
return writer.toBuffer();
|
|
645
|
-
}
|
|
660
|
+
},
|
|
646
661
|
};
|
|
647
662
|
/**
|
|
648
663
|
* [SRV description]
|
|
@@ -652,34 +667,34 @@ Packet.Resource.SOA = {
|
|
|
652
667
|
Packet.Resource.SRV = {
|
|
653
668
|
decode: function(reader, length) {
|
|
654
669
|
this.priority = reader.read(16);
|
|
655
|
-
this.weight
|
|
656
|
-
this.port
|
|
657
|
-
this.target
|
|
670
|
+
this.weight = reader.read(16);
|
|
671
|
+
this.port = reader.read(16);
|
|
672
|
+
this.target = Packet.Name.decode(reader);
|
|
658
673
|
return this;
|
|
659
674
|
},
|
|
660
675
|
encode: function(record, writer) {
|
|
661
676
|
writer = writer || new Packet.Writer();
|
|
662
677
|
const { length } = Packet.Name.encode(record.target);
|
|
663
|
-
writer.write(length + 6
|
|
678
|
+
writer.write(length + 6, 16);
|
|
664
679
|
writer.write(record.priority, 16);
|
|
665
|
-
writer.write(record.weight
|
|
666
|
-
writer.write(record.port
|
|
680
|
+
writer.write(record.weight, 16);
|
|
681
|
+
writer.write(record.port, 16);
|
|
667
682
|
Packet.Name.encode(record.target, writer);
|
|
668
683
|
return writer.toBuffer();
|
|
669
|
-
}
|
|
684
|
+
},
|
|
670
685
|
};
|
|
671
686
|
|
|
672
687
|
Packet.Resource.EDNS = function(rdata) {
|
|
673
688
|
return {
|
|
674
|
-
type: Packet.TYPE
|
|
675
|
-
class: 512, // Supported UDP Payload size
|
|
676
|
-
ttl: 0, // Extended RCODE and flags
|
|
677
|
-
rdata // Objects of type Packet.Resource.EDNS.*
|
|
689
|
+
type : Packet.TYPE.EDNS,
|
|
690
|
+
class : 512, // Supported UDP Payload size
|
|
691
|
+
ttl : 0, // Extended RCODE and flags
|
|
692
|
+
rdata, // Objects of type Packet.Resource.EDNS.*
|
|
678
693
|
};
|
|
679
694
|
};
|
|
680
695
|
|
|
681
696
|
Packet.Resource.EDNS.decode = function(reader, length) {
|
|
682
|
-
this.type = Packet.TYPE
|
|
697
|
+
this.type = Packet.TYPE.EDNS;
|
|
683
698
|
this.class = 512;
|
|
684
699
|
this.ttl = 0;
|
|
685
700
|
this.rdata = [];
|
|
@@ -689,10 +704,10 @@ Packet.Resource.EDNS.decode = function(reader, length) {
|
|
|
689
704
|
const optionLength = reader.read(16); // In octet (https://tools.ietf.org/html/rfc6891#page-8)
|
|
690
705
|
|
|
691
706
|
const decoder = Object.keys(Packet.EDNS_OPTION_CODE).filter(function(type) {
|
|
692
|
-
return optionCode
|
|
707
|
+
return optionCode === Packet.EDNS_OPTION_CODE[type];
|
|
693
708
|
})[0];
|
|
694
|
-
if (decoder in Packet.Resource.EDNS && Packet.Resource.EDNS[
|
|
695
|
-
const rdata = Packet.Resource.EDNS[
|
|
709
|
+
if (decoder in Packet.Resource.EDNS && Packet.Resource.EDNS[decoder].decode) {
|
|
710
|
+
const rdata = Packet.Resource.EDNS[decoder].decode(reader, optionLength);
|
|
696
711
|
this.rdata.push(rdata);
|
|
697
712
|
} else {
|
|
698
713
|
reader.read(optionLength); // Ignore data that doesn't understand
|
|
@@ -706,16 +721,16 @@ Packet.Resource.EDNS.decode = function(reader, length) {
|
|
|
706
721
|
|
|
707
722
|
Packet.Resource.EDNS.encode = function(record, writer) {
|
|
708
723
|
const rdataWriter = new Packet.Writer();
|
|
709
|
-
for(
|
|
710
|
-
|
|
711
|
-
return rdata.ednsCode
|
|
724
|
+
for (const rdata of record.rdata) {
|
|
725
|
+
const encoder = Object.keys(Packet.EDNS_OPTION_CODE).filter(function(type) {
|
|
726
|
+
return rdata.ednsCode === Packet.EDNS_OPTION_CODE[type];
|
|
712
727
|
})[0];
|
|
713
|
-
if(encoder in Packet.Resource.EDNS && Packet.Resource.EDNS[
|
|
728
|
+
if (encoder in Packet.Resource.EDNS && Packet.Resource.EDNS[encoder].encode) {
|
|
714
729
|
const w = new Packet.Writer();
|
|
715
|
-
Packet.Resource.EDNS[
|
|
730
|
+
Packet.Resource.EDNS[encoder].encode(rdata, w);
|
|
716
731
|
rdataWriter.write(rdata.ednsCode, 16);
|
|
717
732
|
rdataWriter.write(w.buffer.length / 8, 16);
|
|
718
|
-
rdataWriter.writeBuffer(w)
|
|
733
|
+
rdataWriter.writeBuffer(w);
|
|
719
734
|
} else {
|
|
720
735
|
debug('node-dns > unknown EDNS rdata encoder %s(%j)', encoder, rdata.ednsCode);
|
|
721
736
|
}
|
|
@@ -727,16 +742,16 @@ Packet.Resource.EDNS.encode = function(record, writer) {
|
|
|
727
742
|
};
|
|
728
743
|
|
|
729
744
|
Packet.Resource.EDNS.ECS = function(clientIp) {
|
|
730
|
-
const [ip, prefixLength] = clientIp.split('/');
|
|
745
|
+
const [ ip, prefixLength ] = clientIp.split('/');
|
|
731
746
|
const numPrefixLength = parseInt(prefixLength) || 32;
|
|
732
747
|
return {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
748
|
+
ednsCode : Packet.EDNS_OPTION_CODE.ECS,
|
|
749
|
+
family : 1,
|
|
750
|
+
sourcePrefixLength : numPrefixLength,
|
|
751
|
+
scopePrefixLength : 0,
|
|
752
|
+
ip,
|
|
738
753
|
};
|
|
739
|
-
}
|
|
754
|
+
};
|
|
740
755
|
|
|
741
756
|
Packet.Resource.EDNS.ECS.decode = function(reader, length) {
|
|
742
757
|
const rdata = {};
|
|
@@ -762,10 +777,10 @@ Packet.Resource.EDNS.ECS.decode = function(reader, length) {
|
|
|
762
777
|
}
|
|
763
778
|
rdata.ip = ipv4Octets.join('.');
|
|
764
779
|
return rdata;
|
|
765
|
-
}
|
|
780
|
+
};
|
|
766
781
|
|
|
767
782
|
Packet.Resource.EDNS.ECS.encode = function(record, writer) {
|
|
768
|
-
const ip = record.ip.split('.').map(
|
|
783
|
+
const ip = record.ip.split('.').map(s => parseInt(s));
|
|
769
784
|
writer.write(record.family, 16);
|
|
770
785
|
writer.write(record.sourcePrefixLength, 8);
|
|
771
786
|
writer.write(record.scopePrefixLength, 8);
|
|
@@ -773,13 +788,13 @@ Packet.Resource.EDNS.ECS.encode = function(record, writer) {
|
|
|
773
788
|
writer.write(ip[1], 8);
|
|
774
789
|
writer.write(ip[2], 8);
|
|
775
790
|
writer.write(ip[3], 8);
|
|
776
|
-
}
|
|
791
|
+
};
|
|
777
792
|
|
|
778
793
|
Packet.Resource.CAA = {
|
|
779
794
|
encode: function(record, writer) {
|
|
780
795
|
writer = writer || new Packet.Writer();
|
|
781
796
|
|
|
782
|
-
const buffer =
|
|
797
|
+
const buffer = Buffer.from(record.tag + record.value, 'utf8');
|
|
783
798
|
writer.write(2 + buffer.length, 16);
|
|
784
799
|
writer.write(record.flags, 8);
|
|
785
800
|
writer.write(record.tag.length, 8);
|
|
@@ -788,7 +803,7 @@ Packet.Resource.CAA = {
|
|
|
788
803
|
writer.write(c, 8);
|
|
789
804
|
});
|
|
790
805
|
return writer.toBuffer();
|
|
791
|
-
}
|
|
806
|
+
},
|
|
792
807
|
};
|
|
793
808
|
|
|
794
809
|
Packet.Reader = BufferReader;
|
|
@@ -805,7 +820,7 @@ Packet.createResourceFromQuestion = function(base, record) {
|
|
|
805
820
|
const resource = new Packet.Resource(base);
|
|
806
821
|
Object.assign(resource, record);
|
|
807
822
|
return resource;
|
|
808
|
-
}
|
|
823
|
+
};
|
|
809
824
|
|
|
810
825
|
Packet.readStream = socket => {
|
|
811
826
|
let chunks = [];
|
|
@@ -829,7 +844,7 @@ Packet.readStream = socket => {
|
|
|
829
844
|
}
|
|
830
845
|
if (!expected && chunklen >= 2) {
|
|
831
846
|
if (chunks.length > 1) {
|
|
832
|
-
chunks = [Buffer.concat(chunks, chunklen)];
|
|
847
|
+
chunks = [ Buffer.concat(chunks, chunklen) ];
|
|
833
848
|
}
|
|
834
849
|
expected = chunks[0].readUInt16BE(0);
|
|
835
850
|
}
|
|
@@ -849,9 +864,9 @@ Packet.prototype.toBase64URL = function() {
|
|
|
849
864
|
const buffer = this.toBuffer();
|
|
850
865
|
const base64 = buffer.toString('base64');
|
|
851
866
|
return base64
|
|
852
|
-
.replace(/=/g,
|
|
853
|
-
.replace(/\+/g,
|
|
854
|
-
.replace(/\//g,
|
|
867
|
+
.replace(/=/g, '')
|
|
868
|
+
.replace(/\+/g, '-')
|
|
869
|
+
.replace(/\//g, '_');
|
|
855
870
|
};
|
|
856
871
|
|
|
857
872
|
module.exports = Packet;
|