node.d/snmp: snmpv3 support (#7802)
* node.d.plugin/node_modules: update net-snmp.js to the latest (snmp v3 support) * node.d/snmp.node.js: create v3 session if snmp version is 3 * node.d/snmp/README.md: update
Ilya Mashchenko committed
Jan 22, 2020 at 18:05 UTC
b93aaad43c5861d1ba47df62cd07ca0e3223455a
3 files changed
+3419
-1357
collectors/node.d.plugin/node_modules/net-snmp.js
+3199
-1212
@@ -1,66 +1,77 @@
1
-
1
// Copyright 2013 Stephen Vickers <stephen.vickers.sv@gmail.com>
2
// SPDX-License-Identifier: MIT
3
5
-var ber = require ("asn1-ber").Ber;
6
-var dgram = require ("dgram");
7
-var events = require ("events");
8
-var util = require ("util");
4
+var ber = require("asn1-ber").Ber;
5
+var dgram = require("dgram");
6
+var events = require("events");
7
+var util = require("util");
8
+var crypto = require("crypto");
9
+
10
+var DEBUG = false;
11
+
12
+var MAX_INT32 = 2147483647;
13
+
14
+function debug(line) {
15
+ if (DEBUG) {
16
+ console.debug(line);
17
+ }
18
+}
19
20
/*****************************************************************************
21
** Constants
22
**/
23
14
-function _expandConstantObject (object) {
15
- var keys = [];
16
- for (var key in object)
17
- keys.push (key);
18
- for (var i = 0; i < keys.length; i++)
19
- object[object[keys[i]]] = parseInt (keys[i]);
24
+
25
+function _expandConstantObject(object) {
26
+ var keys = [];
27
+ for (var key in object)
28
+ keys.push(key);
29
+ for (var i = 0; i < keys.length; i++)
30
+ object[object[keys[i]]] = parseInt(keys[i]);
31
}
32
33
var ErrorStatus = {
23
- 0: "NoError",
24
- 1: "TooBig",
25
- 2: "NoSuchName",
26
- 3: "BadValue",
27
- 4: "ReadOnly",
28
- 5: "GeneralError",
29
- 6: "NoAccess",
30
- 7: "WrongType",
31
- 8: "WrongLength",
32
- 9: "WrongEncoding",
33
- 10: "WrongValue",
34
- 11: "NoCreation",
35
- 12: "InconsistentValue",
36
- 13: "ResourceUnavailable",
37
- 14: "CommitFailed",
38
- 15: "UndoFailed",
39
- 16: "AuthorizationError",
40
- 17: "NotWritable",
41
- 18: "InconsistentName"
42
-};
43
-
44
-_expandConstantObject (ErrorStatus);
34
+ 0: "NoError",
35
+ 1: "TooBig",
36
+ 2: "NoSuchName",
37
+ 3: "BadValue",
38
+ 4: "ReadOnly",
39
+ 5: "GeneralError",
40
+ 6: "NoAccess",
41
+ 7: "WrongType",
42
+ 8: "WrongLength",
43
+ 9: "WrongEncoding",
44
+ 10: "WrongValue",
45
+ 11: "NoCreation",
46
+ 12: "InconsistentValue",
47
+ 13: "ResourceUnavailable",
48
+ 14: "CommitFailed",
49
+ 15: "UndoFailed",
50
+ 16: "AuthorizationError",
51
+ 17: "NotWritable",
52
+ 18: "InconsistentName"
53
+};
54
+
55
+_expandConstantObject(ErrorStatus);
56
57
var ObjectType = {
47
- 1: "Boolean",
48
- 2: "Integer",
49
- 4: "OctetString",
50
- 5: "Null",
51
- 6: "OID",
52
- 64: "IpAddress",
53
- 65: "Counter",
54
- 66: "Gauge",
55
- 67: "TimeTicks",
56
- 68: "Opaque",
57
- 70: "Counter64",
58
- 128: "NoSuchObject",
59
- 129: "NoSuchInstance",
60
- 130: "EndOfMibView"
61
-};
62
-
63
-_expandConstantObject (ObjectType);
58
+ 1: "Boolean",
59
+ 2: "Integer",
60
+ 4: "OctetString",
61
+ 5: "Null",
62
+ 6: "OID",
63
+ 64: "IpAddress",
64
+ 65: "Counter",
65
+ 66: "Gauge",
66
+ 67: "TimeTicks",
67
+ 68: "Opaque",
68
+ 70: "Counter64",
69
+ 128: "NoSuchObject",
70
+ 129: "NoSuchInstance",
71
+ 130: "EndOfMibView"
72
+};
73
+
74
+_expandConstantObject(ObjectType);
75
76
ObjectType.Integer32 = ObjectType.Integer;
77
ObjectType.Counter32 = ObjectType.Counter;
@@ -68,132 +79,173 @@ ObjectType.Gauge32 = ObjectType.Gauge;
79
ObjectType.Unsigned32 = ObjectType.Gauge32;
80
81
var PduType = {
71
- 160: "GetRequest",
72
- 161: "GetNextRequest",
73
- 162: "GetResponse",
74
- 163: "SetRequest",
75
- 164: "Trap",
76
- 165: "GetBulkRequest",
77
- 166: "InformRequest",
78
- 167: "TrapV2",
79
- 168: "Report"
82
+ 160: "GetRequest",
83
+ 161: "GetNextRequest",
84
+ 162: "GetResponse",
85
+ 163: "SetRequest",
86
+ 164: "Trap",
87
+ 165: "GetBulkRequest",
88
+ 166: "InformRequest",
89
+ 167: "TrapV2",
90
+ 168: "Report"
91
};
92
82
-_expandConstantObject (PduType);
93
+_expandConstantObject(PduType);
94
95
var TrapType = {
85
- 0: "ColdStart",
86
- 1: "WarmStart",
87
- 2: "LinkDown",
88
- 3: "LinkUp",
89
- 4: "AuthenticationFailure",
90
- 5: "EgpNeighborLoss",
91
- 6: "EnterpriseSpecific"
96
+ 0: "ColdStart",
97
+ 1: "WarmStart",
98
+ 2: "LinkDown",
99
+ 3: "LinkUp",
100
+ 4: "AuthenticationFailure",
101
+ 5: "EgpNeighborLoss",
102
+ 6: "EnterpriseSpecific"
103
+};
104
+
105
+_expandConstantObject(TrapType);
106
+
107
+var SecurityLevel = {
108
+ 1: "noAuthNoPriv",
109
+ 2: "authNoPriv",
110
+ 3: "authPriv"
111
+};
112
+
113
+_expandConstantObject(SecurityLevel);
114
+
115
+var AuthProtocols = {
116
+ "1": "none",
117
+ "2": "md5",
118
+ "3": "sha"
119
+};
120
+
121
+_expandConstantObject(AuthProtocols);
122
+
123
+var PrivProtocols = {
124
+ "1": "none",
125
+ "2": "des"
126
+};
127
+
128
+_expandConstantObject(PrivProtocols);
129
+
130
+var MibProviderType = {
131
+ "1": "Scalar",
132
+ "2": "Table"
133
};
134
94
-_expandConstantObject (TrapType);
135
+_expandConstantObject(MibProviderType);
136
137
var Version1 = 0;
138
var Version2c = 1;
139
+var Version3 = 3;
140
+
141
+var Version = {
142
+ "1": Version1,
143
+ "2c": Version2c,
144
+ "3": Version3
145
+};
146
147
/*****************************************************************************
148
** Exception class definitions
149
**/
150
103
-function ResponseInvalidError (message) {
104
- this.name = "ResponseInvalidError";
105
- this.message = message;
106
- Error.captureStackTrace(this, ResponseInvalidError);
151
+function ResponseInvalidError(message) {
152
+ this.name = "ResponseInvalidError";
153
+ this.message = message;
154
+ Error.captureStackTrace(this, ResponseInvalidError);
155
}
108
-util.inherits (ResponseInvalidError, Error);
156
110
-function RequestInvalidError (message) {
111
- this.name = "RequestInvalidError";
112
- this.message = message;
113
- Error.captureStackTrace(this, RequestInvalidError);
157
+util.inherits(ResponseInvalidError, Error);
158
+
159
+function RequestInvalidError(message) {
160
+ this.name = "RequestInvalidError";
161
+ this.message = message;
162
+ Error.captureStackTrace(this, RequestInvalidError);
163
}
115
-util.inherits (RequestInvalidError, Error);
164
117
-function RequestFailedError (message, status) {
118
- this.name = "RequestFailedError";
119
- this.message = message;
120
- this.status = status;
121
- Error.captureStackTrace(this, RequestFailedError);
165
+util.inherits(RequestInvalidError, Error);
166
+
167
+function RequestFailedError(message, status) {
168
+ this.name = "RequestFailedError";
169
+ this.message = message;
170
+ this.status = status;
171
+ Error.captureStackTrace(this, RequestFailedError);
172
}
123
-util.inherits (RequestFailedError, Error);
173
125
-function RequestTimedOutError (message) {
126
- this.name = "RequestTimedOutError";
127
- this.message = message;
128
- Error.captureStackTrace(this, RequestTimedOutError);
174
+util.inherits(RequestFailedError, Error);
175
+
176
+function RequestTimedOutError(message) {
177
+ this.name = "RequestTimedOutError";
178
+ this.message = message;
179
+ Error.captureStackTrace(this, RequestTimedOutError);
180
}
130
-util.inherits (RequestTimedOutError, Error);
181
+
182
+util.inherits(RequestTimedOutError, Error);
183
184
/*****************************************************************************
185
** OID and varbind helper functions
186
**/
187
136
-function isVarbindError (varbind) {
137
- return !!(varbind.type == ObjectType.NoSuchObject
138
- || varbind.type == ObjectType.NoSuchInstance
139
- || varbind.type == ObjectType.EndOfMibView);
188
+function isVarbindError(varbind) {
189
+ return !!(varbind.type == ObjectType.NoSuchObject
190
+ || varbind.type == ObjectType.NoSuchInstance
191
+ || varbind.type == ObjectType.EndOfMibView);
192
}
193
142
-function varbindError (varbind) {
143
- return (ObjectType[varbind.type] || "NotAnError") + ": " + varbind.oid;
194
+function varbindError(varbind) {
195
+ return (ObjectType[varbind.type] || "NotAnError") + ": " + varbind.oid;
196
}
197
146
-function oidFollowsOid (oidString, nextString) {
147
- var oid = {str: oidString, len: oidString.length, idx: 0};
148
- var next = {str: nextString, len: nextString.length, idx: 0};
149
- var dotCharCode = ".".charCodeAt (0);
150
-
151
- function getNumber (item) {
152
- var n = 0;
153
- if (item.idx >= item.len)
154
- return null;
155
- while (item.idx < item.len) {
156
- var charCode = item.str.charCodeAt (item.idx++);
157
- if (charCode == dotCharCode)
158
- return n;
159
- n = (n ? (n * 10) : n) + (charCode - 48);
160
- }
161
- return n;
162
- }
163
-
164
- while (1) {
165
- var oidNumber = getNumber (oid);
166
- var nextNumber = getNumber (next);
167
-
168
- if (oidNumber !== null) {
169
- if (nextNumber !== null) {
170
- if (nextNumber > oidNumber) {
171
- return true;
172
- } else if (nextNumber < oidNumber) {
173
- return false;
174
- }
175
- } else {
176
- return true;
177
- }
178
- } else {
179
- return true;
180
- }
181
- }
198
+function oidFollowsOid(oidString, nextString) {
199
+ var oid = {str: oidString, len: oidString.length, idx: 0};
200
+ var next = {str: nextString, len: nextString.length, idx: 0};
201
+ var dotCharCode = ".".charCodeAt(0);
202
+
203
+ function getNumber(item) {
204
+ var n = 0;
205
+ if (item.idx >= item.len)
206
+ return null;
207
+ while (item.idx < item.len) {
208
+ var charCode = item.str.charCodeAt(item.idx++);
209
+ if (charCode == dotCharCode)
210
+ return n;
211
+ n = (n ? (n * 10) : n) + (charCode - 48);
212
+ }
213
+ return n;
214
+ }
215
+
216
+ while (1) {
217
+ var oidNumber = getNumber(oid);
218
+ var nextNumber = getNumber(next);
219
+
220
+ if (oidNumber !== null) {
221
+ if (nextNumber !== null) {
222
+ if (nextNumber > oidNumber) {
223
+ return true;
224
+ } else if (nextNumber < oidNumber) {
225
+ return false;
226
+ }
227
+ } else {
228
+ return true;
229
+ }
230
+ } else {
231
+ return true;
232
+ }
233
+ }
234
}
235
184
-function oidInSubtree (oidString, nextString) {
185
- var oid = oidString.split (".");
186
- var next = nextString.split (".");
236
+function oidInSubtree(oidString, nextString) {
237
+ var oid = oidString.split(".");
238
+ var next = nextString.split(".");
239
188
- if (oid.length > next.length)
189
- return false;
240
+ if (oid.length > next.length)
241
+ return false;
242
191
- for (var i = 0; i < oid.length; i++) {
192
- if (next[i] != oid[i])
193
- return false;
194
- }
243
+ for (var i = 0; i < oid.length; i++) {
244
+ if (next[i] != oid[i])
245
+ return false;
246
+ }
247
196
- return true;
248
+ return true;
249
}
250
251
/**
@@ -207,1228 +259,3138 @@ function oidInSubtree (oidString, nextString) {
259
** an error since the integer is too large.
260
**/
261
210
-function readInt (buffer) {
211
- return readUint (buffer, true);
262
+function readInt(buffer) {
263
+ return readUint(buffer, true);
264
+}
265
+
266
+function readIpAddress(buffer) {
267
+ var bytes = buffer.readString(ObjectType.IpAddress, true);
268
+ if (bytes.length != 4)
269
+ throw new ResponseInvalidError("Length '" + bytes.length
270
+ + "' of IP address '" + bytes.toString("hex")
271
+ + "' is not 4");
272
+ var value = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
273
+ return value;
274
}
275
214
-function readUint (buffer, isSigned) {
215
- buffer.readByte ();
216
- var length = buffer.readByte ();
217
- var value = 0;
218
- var signedBitSet = false;
219
-
220
- if (length > 5) {
221
- throw new RangeError ("Integer too long '" + length + "'");
222
- } else if (length == 5) {
223
- if (buffer.readByte () !== 0)
224
- throw new RangeError ("Integer too long '" + length + "'");
225
- length = 4;
226
- }
227
-
228
- for (var i = 0; i < length; i++) {
229
- value *= 256;
230
- value += buffer.readByte ();
231
-
232
- if (isSigned && i <= 0) {
233
- if ((value & 0x80) == 0x80)
234
- signedBitSet = true;
235
- }
236
- }
237
-
238
- if (signedBitSet)
239
- value -= (1 << (i * 8));
240
-
241
- return value;
276
+function readUint(buffer, isSigned) {
277
+ buffer.readByte();
278
+ var length = buffer.readByte();
279
+ var value = 0;
280
+ var signedBitSet = false;
281
+
282
+ if (length > 5) {
283
+ throw new RangeError("Integer too long '" + length + "'");
284
+ } else if (length == 5) {
285
+ if (buffer.readByte() !== 0)
286
+ throw new RangeError("Integer too long '" + length + "'");
287
+ length = 4;
288
+ }
289
+
290
+ for (var i = 0; i < length; i++) {
291
+ value *= 256;
292
+ value += buffer.readByte();
293
+
294
+ if (isSigned && i <= 0) {
295
+ if ((value & 0x80) == 0x80)
296
+ signedBitSet = true;
297
+ }
298
+ }
299
+
300
+ if (signedBitSet)
301
+ value -= (1 << (i * 8));
302
+
303
+ return value;
304
}
305
244
-function readUint64 (buffer) {
245
- var value = buffer.readString (ObjectType.Counter64, true);
306
+function readUint64(buffer) {
307
+ var value = buffer.readString(ObjectType.Counter64, true);
308
247
- return value;
309
+ return value;
310
}
311
250
-function readVarbinds (buffer, varbinds) {
251
- buffer.readSequence ();
252
-
253
- while (1) {
254
- buffer.readSequence ();
255
- var oid = buffer.readOID ();
256
- var type = buffer.peek ();
257
-
258
- if (type == null)
259
- break;
260
-
261
- var value;
262
-
263
- if (type == ObjectType.Boolean) {
264
- value = buffer.readBoolean ();
265
- } else if (type == ObjectType.Integer) {
266
- value = readInt (buffer);
267
- } else if (type == ObjectType.OctetString) {
268
- value = buffer.readString (null, true);
269
- } else if (type == ObjectType.Null) {
270
- buffer.readByte ();
271
- buffer.readByte ();
272
- value = null;
273
- } else if (type == ObjectType.OID) {
274
- value = buffer.readOID ();
275
- } else if (type == ObjectType.IpAddress) {
276
- var bytes = buffer.readString (ObjectType.IpAddress, true);
277
- if (bytes.length != 4)
278
- throw new ResponseInvalidError ("Length '" + bytes.length
279
- + "' of IP address '" + bytes.toString ("hex")
280
- + "' is not 4");
281
- value = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
282
- } else if (type == ObjectType.Counter) {
283
- value = readUint (buffer);
284
- } else if (type == ObjectType.Gauge) {
285
- value = readUint (buffer);
286
- } else if (type == ObjectType.TimeTicks) {
287
- value = readUint (buffer);
288
- } else if (type == ObjectType.Opaque) {
289
- value = buffer.readString (ObjectType.Opaque, true);
290
- } else if (type == ObjectType.Counter64) {
291
- value = readUint64 (buffer);
292
- } else if (type == ObjectType.NoSuchObject) {
293
- buffer.readByte ();
294
- buffer.readByte ();
295
- value = null;
296
- } else if (type == ObjectType.NoSuchInstance) {
297
- buffer.readByte ();
298
- buffer.readByte ();
299
- value = null;
300
- } else if (type == ObjectType.EndOfMibView) {
301
- buffer.readByte ();
302
- buffer.readByte ();
303
- value = null;
304
- } else {
305
- throw new ResponseInvalidError ("Unknown type '" + type
306
- + "' in response");
307
- }
308
-
309
- varbinds.push ({
310
- oid: oid,
311
- type: type,
312
- value: value
313
- });
314
- }
312
+function readVarbinds(buffer, varbinds) {
313
+ buffer.readSequence();
314
+
315
+ while (1) {
316
+ buffer.readSequence();
317
+ if (buffer.peek() != ObjectType.OID)
318
+ break;
319
+ var oid = buffer.readOID();
320
+ var type = buffer.peek();
321
+
322
+ if (type == null)
323
+ break;
324
+
325
+ var value;
326
+
327
+ if (type == ObjectType.Boolean) {
328
+ value = buffer.readBoolean();
329
+ } else if (type == ObjectType.Integer) {
330
+ value = readInt(buffer);
331
+ } else if (type == ObjectType.OctetString) {
332
+ value = buffer.readString(null, true);
333
+ } else if (type == ObjectType.Null) {
334
+ buffer.readByte();
335
+ buffer.readByte();
336
+ value = null;
337
+ } else if (type == ObjectType.OID) {
338
+ value = buffer.readOID();
339
+ } else if (type == ObjectType.IpAddress) {
340
+ var bytes = buffer.readString(ObjectType.IpAddress, true);
341
+ if (bytes.length != 4)
342
+ throw new ResponseInvalidError("Length '" + bytes.length
343
+ + "' of IP address '" + bytes.toString("hex")
344
+ + "' is not 4");
345
+ value = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
346
+ } else if (type == ObjectType.Counter) {
347
+ value = readUint(buffer);
348
+ } else if (type == ObjectType.Gauge) {
349
+ value = readUint(buffer);
350
+ } else if (type == ObjectType.TimeTicks) {
351
+ value = readUint(buffer);
352
+ } else if (type == ObjectType.Opaque) {
353
+ value = buffer.readString(ObjectType.Opaque, true);
354
+ } else if (type == ObjectType.Counter64) {
355
+ value = readUint64(buffer);
356
+ } else if (type == ObjectType.NoSuchObject) {
357
+ buffer.readByte();
358
+ buffer.readByte();
359
+ value = null;
360
+ } else if (type == ObjectType.NoSuchInstance) {
361
+ buffer.readByte();
362
+ buffer.readByte();
363
+ value = null;
364
+ } else if (type == ObjectType.EndOfMibView) {
365
+ buffer.readByte();
366
+ buffer.readByte();
367
+ value = null;
368
+ } else {
369
+ throw new ResponseInvalidError("Unknown type '" + type
370
+ + "' in response");
371
+ }
372
+
373
+ varbinds.push({
374
+ oid: oid,
375
+ type: type,
376
+ value: value
377
+ });
378
+ }
379
}
380
317
-function writeUint (buffer, type, value) {
318
- var b = new Buffer (4);
319
- b.writeUInt32BE (value, 0);
320
- buffer.writeBuffer (b, type);
381
+function writeUint(buffer, type, value) {
382
+ var b = Buffer.alloc(4);
383
+ b.writeUInt32BE(value, 0);
384
+ buffer.writeBuffer(b, type);
385
}
386
323
-function writeUint64 (buffer, value) {
324
- buffer.writeBuffer (value, ObjectType.Counter64);
387
+function writeUint64(buffer, value) {
388
+ buffer.writeBuffer(value, ObjectType.Counter64);
389
}
390
327
-function writeVarbinds (buffer, varbinds) {
328
- buffer.startSequence ();
329
- for (var i = 0; i < varbinds.length; i++) {
330
- buffer.startSequence ();
331
- buffer.writeOID (varbinds[i].oid);
332
-
333
- if (varbinds[i].type && varbinds[i].hasOwnProperty("value")) {
334
- var type = varbinds[i].type;
335
- var value = varbinds[i].value;
336
-
337
- if (type == ObjectType.Boolean) {
338
- buffer.writeBoolean (value ? true : false);
339
- } else if (type == ObjectType.Integer) { // also Integer32
340
- buffer.writeInt (value);
341
- } else if (type == ObjectType.OctetString) {
342
- if (typeof value == "string")
343
- buffer.writeString (value);
344
- else
345
- buffer.writeBuffer (value, ObjectType.OctetString);
346
- } else if (type == ObjectType.Null) {
347
- buffer.writeNull ();
348
- } else if (type == ObjectType.OID) {
349
- buffer.writeOID (value);
350
- } else if (type == ObjectType.IpAddress) {
351
- var bytes = value.split (".");
352
- if (bytes.length != 4)
353
- throw new RequestInvalidError ("Invalid IP address '"
354
- + value + "'");
355
- buffer.writeBuffer (new Buffer (bytes), 64);
356
- } else if (type == ObjectType.Counter) { // also Counter32
357
- writeUint (buffer, ObjectType.Counter, value);
358
- } else if (type == ObjectType.Gauge) { // also Gauge32 & Unsigned32
359
- writeUint (buffer, ObjectType.Gauge, value);
360
- } else if (type == ObjectType.TimeTicks) {
361
- writeUint (buffer, ObjectType.TimeTicks, value);
362
- } else if (type == ObjectType.Opaque) {
363
- buffer.writeBuffer (value, ObjectType.Opaque);
364
- } else if (type == ObjectType.Counter64) {
365
- writeUint64 (buffer, value);
366
- } else {
367
- throw new RequestInvalidError ("Unknown type '" + type
368
- + "' in request");
369
- }
370
- } else {
371
- buffer.writeNull ();
372
- }
373
-
374
- buffer.endSequence ();
375
- }
376
- buffer.endSequence ();
391
+function writeVarbinds(buffer, varbinds) {
392
+ buffer.startSequence();
393
+ for (var i = 0; i < varbinds.length; i++) {
394
+ buffer.startSequence();
395
+ buffer.writeOID(varbinds[i].oid);
396
+
397
+ if (varbinds[i].type && varbinds[i].hasOwnProperty("value")) {
398
+ var type = varbinds[i].type;
399
+ var value = varbinds[i].value;
400
+
401
+ if (type == ObjectType.Boolean) {
402
+ buffer.writeBoolean(value ? true : false);
403
+ } else if (type == ObjectType.Integer) { // also Integer32
404
+ buffer.writeInt(value);
405
+ } else if (type == ObjectType.OctetString) {
406
+ if (typeof value == "string")
407
+ buffer.writeString(value);
408
+ else
409
+ buffer.writeBuffer(value, ObjectType.OctetString);
410
+ } else if (type == ObjectType.Null) {
411
+ buffer.writeNull();
412
+ } else if (type == ObjectType.OID) {
413
+ buffer.writeOID(value);
414
+ } else if (type == ObjectType.IpAddress) {
415
+ var bytes = value.split(".");
416
+ if (bytes.length != 4)
417
+ throw new RequestInvalidError("Invalid IP address '"
418
+ + value + "'");
419
+ buffer.writeBuffer(Buffer.from(bytes), 64);
420
+ } else if (type == ObjectType.Counter) { // also Counter32
421
+ writeUint(buffer, ObjectType.Counter, value);
422
+ } else if (type == ObjectType.Gauge) { // also Gauge32 & Unsigned32
423
+ writeUint(buffer, ObjectType.Gauge, value);
424
+ } else if (type == ObjectType.TimeTicks) {
425
+ writeUint(buffer, ObjectType.TimeTicks, value);
426
+ } else if (type == ObjectType.Opaque) {
427
+ buffer.writeBuffer(value, ObjectType.Opaque);
428
+ } else if (type == ObjectType.Counter64) {
429
+ writeUint64(buffer, value);
430
+ } else if (type == ObjectType.EndOfMibView) {
431
+ buffer.writeByte(130);
432
+ buffer.writeByte(0);
433
+ } else {
434
+ throw new RequestInvalidError("Unknown type '" + type
435
+ + "' in request");
436
+ }
437
+ } else {
438
+ buffer.writeNull();
439
+ }
440
+
441
+ buffer.endSequence();
442
+ }
443
+ buffer.endSequence();
444
}
445
446
/*****************************************************************************
447
** PDU class definitions
448
**/
449
383
-var SimplePdu = function (id, varbinds, options) {
384
- this.id = id;
385
- this.varbinds = varbinds;
386
- this.options = options || {};
450
+var SimplePdu = function () {
451
};
452
453
SimplePdu.prototype.toBuffer = function (buffer) {
390
- buffer.startSequence (this.type);
454
+ buffer.startSequence(this.type);
455
392
- buffer.writeInt (this.id);
393
- buffer.writeInt ((this.type == PduType.GetBulkRequest)
394
- ? (this.options.nonRepeaters || 0)
395
- : 0);
396
- buffer.writeInt ((this.type == PduType.GetBulkRequest)
397
- ? (this.options.maxRepetitions || 0)
398
- : 0);
456
+ buffer.writeInt(this.id);
457
+ buffer.writeInt((this.type == PduType.GetBulkRequest)
458
+ ? (this.options.nonRepeaters || 0)
459
+ : 0);
460
+ buffer.writeInt((this.type == PduType.GetBulkRequest)
461
+ ? (this.options.maxRepetitions || 0)
462
+ : 0);
463
400
- writeVarbinds (buffer, this.varbinds);
464
+ writeVarbinds(buffer, this.varbinds);
465
402
- buffer.endSequence ();
466
+ buffer.endSequence();
467
};
468
405
-var GetBulkRequestPdu = function () {
406
- this.type = PduType.GetBulkRequest;
407
- GetBulkRequestPdu.super_.apply (this, arguments);
408
-};
469
+SimplePdu.prototype.initializeFromVariables = function (id, varbinds, options) {
470
+ this.id = id;
471
+ this.varbinds = varbinds;
472
+ this.options = options || {};
473
+ this.contextName = (options && options.context) ? options.context : "";
474
+}
475
410
-util.inherits (GetBulkRequestPdu, SimplePdu);
476
+SimplePdu.prototype.initializeFromBuffer = function (reader) {
477
+ this.type = reader.peek();
478
+ reader.readSequence();
479
+
480
+ this.id = reader.readInt();
481
+ this.nonRepeaters = reader.readInt();
482
+ this.maxRepetitions = reader.readInt();
483
+
484
+ this.varbinds = [];
485
+ readVarbinds(reader, this.varbinds);
486
412
-var GetNextRequestPdu = function () {
413
- this.type = PduType.GetNextRequest;
414
- GetNextRequestPdu.super_.apply (this, arguments);
487
};
488
417
-util.inherits (GetNextRequestPdu, SimplePdu);
489
+SimplePdu.prototype.getResponsePduForRequest = function () {
490
+ var responsePdu = GetResponsePdu.createFromVariables(this.id, [], {});
491
+ if (this.contextEngineID) {
492
+ responsePdu.contextEngineID = this.contextEngineID;
493
+ responsePdu.contextName = this.contextName;
494
+ }
495
+ return responsePdu;
496
+};
497
+
498
+SimplePdu.createFromVariables = function (pduClass, id, varbinds, options) {
499
+ var pdu = new pduClass(id, varbinds, options);
500
+ pdu.id = id;
501
+ pdu.varbinds = varbinds;
502
+ pdu.options = options || {};
503
+ pdu.contextName = (options && options.context) ? options.context : "";
504
+ return pdu;
505
+};
506
419
-var GetResponsePdu = function (buffer) {
420
- this.type = PduType.GetResponse;
507
+var GetBulkRequestPdu = function () {
508
+ this.type = PduType.GetBulkRequest;
509
+ GetBulkRequestPdu.super_.apply(this, arguments);
510
+};
511
422
- buffer.readSequence (this.type);
512
+util.inherits(GetBulkRequestPdu, SimplePdu);
513
424
- this.id = buffer.readInt ();
514
+GetBulkRequestPdu.createFromBuffer = function (reader) {
515
+ var pdu = new GetBulkRequestPdu();
516
+ pdu.initializeFromBuffer(reader);
517
+ return pdu;
518
+};
519
426
- this.errorStatus = buffer.readInt ();
427
- this.errorIndex = buffer.readInt ();
520
+var GetNextRequestPdu = function () {
521
+ this.type = PduType.GetNextRequest;
522
+ GetNextRequestPdu.super_.apply(this, arguments);
523
+};
524
429
- this.varbinds = [];
525
+util.inherits(GetNextRequestPdu, SimplePdu);
526
431
- readVarbinds (buffer, this.varbinds);
527
+GetNextRequestPdu.createFromBuffer = function (reader) {
528
+ var pdu = new GetNextRequestPdu();
529
+ pdu.initializeFromBuffer(reader);
530
+ return pdu;
531
};
532
533
var GetRequestPdu = function () {
435
- this.type = PduType.GetRequest;
436
- GetRequestPdu.super_.apply (this, arguments);
534
+ this.type = PduType.GetRequest;
535
+ GetRequestPdu.super_.apply(this, arguments);
536
+};
537
+
538
+util.inherits(GetRequestPdu, SimplePdu);
539
+
540
+GetRequestPdu.createFromBuffer = function (reader) {
541
+ var pdu = new GetRequestPdu();
542
+ pdu.initializeFromBuffer(reader);
543
+ return pdu;
544
};
545
439
-util.inherits (GetRequestPdu, SimplePdu);
546
+GetRequestPdu.createFromVariables = function (id, varbinds, options) {
547
+ var pdu = new GetRequestPdu();
548
+ pdu.initializeFromVariables(id, varbinds, options);
549
+ return pdu;
550
+};
551
552
var InformRequestPdu = function () {
442
- this.type = PduType.InformRequest;
443
- InformRequestPdu.super_.apply (this, arguments);
553
+ this.type = PduType.InformRequest;
554
+ InformRequestPdu.super_.apply(this, arguments);
555
};
556
446
-util.inherits (InformRequestPdu, SimplePdu);
557
+util.inherits(InformRequestPdu, SimplePdu);
558
+
559
+InformRequestPdu.createFromBuffer = function (reader) {
560
+ var pdu = new InformRequestPdu();
561
+ pdu.initializeFromBuffer(reader);
562
+ return pdu;
563
+};
564
565
var SetRequestPdu = function () {
449
- this.type = PduType.SetRequest;
450
- SetRequestPdu.super_.apply (this, arguments);
566
+ this.type = PduType.SetRequest;
567
+ SetRequestPdu.super_.apply(this, arguments);
568
+};
569
+
570
+util.inherits(SetRequestPdu, SimplePdu);
571
+
572
+SetRequestPdu.createFromBuffer = function (reader) {
573
+ var pdu = new SetRequestPdu();
574
+ pdu.initializeFromBuffer(reader);
575
+ return pdu;
576
};
577
453
-util.inherits (SetRequestPdu, SimplePdu);
578
+var TrapPdu = function () {
579
+ this.type = PduType.Trap;
580
+};
581
455
-var TrapPdu = function (typeOrOid, varbinds, options) {
456
- this.type = PduType.Trap;
582
+TrapPdu.prototype.toBuffer = function (buffer) {
583
+ buffer.startSequence(this.type);
584
458
- this.agentAddr = options.agentAddr || "127.0.0.1";
459
- this.upTime = options.upTime;
585
+ buffer.writeOID(this.enterprise);
586
+ buffer.writeBuffer(Buffer.from(this.agentAddr.split(".")),
587
+ ObjectType.IpAddress);
588
+ buffer.writeInt(this.generic);
589
+ buffer.writeInt(this.specific);
590
+ writeUint(buffer, ObjectType.TimeTicks,
591
+ this.upTime || Math.floor(process.uptime() * 100));
592
461
- if (typeof typeOrOid == "string") {
462
- this.generic = TrapType.EnterpriseSpecific;
463
- this.specific = parseInt (typeOrOid.match (/\.(\d+)$/)[1]);
464
- this.enterprise = typeOrOid.replace (/\.(\d+)$/, "");
465
- } else {
466
- this.generic = typeOrOid;
467
- this.specific = 0;
468
- this.enterprise = "1.3.6.1.4.1";
469
- }
593
+ writeVarbinds(buffer, this.varbinds);
594
471
- this.varbinds = varbinds;
595
+ buffer.endSequence();
596
};
597
474
-TrapPdu.prototype.toBuffer = function (buffer) {
475
- buffer.startSequence (this.type);
598
+TrapPdu.createFromBuffer = function (reader) {
599
+ var pdu = new TrapPdu();
600
+ reader.readSequence();
601
+
602
+ pdu.enterprise = reader.readOID();
603
+ pdu.agentAddr = readIpAddress(reader);
604
+ pdu.generic = reader.readInt();
605
+ pdu.specific = reader.readInt();
606
+ pdu.upTime = readUint(reader)
607
+
608
+ pdu.varbinds = [];
609
+ readVarbinds(reader, pdu.varbinds);
610
+
611
+ return pdu;
612
+};
613
477
- buffer.writeOID (this.enterprise);
478
- buffer.writeBuffer (new Buffer (this.agentAddr.split (".")),
479
- ObjectType.IpAddress);
480
- buffer.writeInt (this.generic);
481
- buffer.writeInt (this.specific);
482
- writeUint (buffer, ObjectType.TimeTicks,
483
- this.upTime || Math.floor (process.uptime () * 100));
614
+TrapPdu.createFromVariables = function (typeOrOid, varbinds, options) {
615
+ var pdu = new TrapPdu();
616
+ pdu.agentAddr = options.agentAddr || "127.0.0.1";
617
+ pdu.upTime = options.upTime;
618
485
- writeVarbinds (buffer, this.varbinds);
619
+ if (typeof typeOrOid == "string") {
620
+ pdu.generic = TrapType.EnterpriseSpecific;
621
+ pdu.specific = parseInt(typeOrOid.match(/\.(\d+)$/)[1]);
622
+ pdu.enterprise = typeOrOid.replace(/\.(\d+)$/, "");
623
+ } else {
624
+ pdu.generic = typeOrOid;
625
+ pdu.specific = 0;
626
+ pdu.enterprise = "1.3.6.1.4.1";
627
+ }
628
487
- buffer.endSequence ();
629
+ pdu.varbinds = varbinds;
630
+
631
+ return pdu;
632
};
633
634
var TrapV2Pdu = function () {
491
- this.type = PduType.TrapV2;
492
- TrapV2Pdu.super_.apply (this, arguments);
635
+ this.type = PduType.TrapV2;
636
+ TrapV2Pdu.super_.apply(this, arguments);
637
+};
638
+
639
+util.inherits(TrapV2Pdu, SimplePdu);
640
+
641
+TrapV2Pdu.createFromBuffer = function (reader) {
642
+ var pdu = new TrapV2Pdu();
643
+ pdu.initializeFromBuffer(reader);
644
+ return pdu;
645
+};
646
+
647
+TrapV2Pdu.createFromVariables = function (id, varbinds, options) {
648
+ var pdu = new TrapV2Pdu();
649
+ pdu.initializeFromVariables(id, varbinds, options);
650
+ return pdu;
651
+};
652
+
653
+var SimpleResponsePdu = function () {
654
+};
655
+
656
+SimpleResponsePdu.prototype.toBuffer = function (writer) {
657
+ writer.startSequence(this.type);
658
+
659
+ writer.writeInt(this.id);
660
+ writer.writeInt(this.errorStatus || 0);
661
+ writer.writeInt(this.errorIndex || 0);
662
+ writeVarbinds(writer, this.varbinds);
663
+ writer.endSequence();
664
+
665
};
666
495
-util.inherits (TrapV2Pdu, SimplePdu);
667
+SimpleResponsePdu.prototype.initializeFromBuffer = function (reader) {
668
+ reader.readSequence(this.type);
669
+
670
+ this.id = reader.readInt();
671
+ this.errorStatus = reader.readInt();
672
+ this.errorIndex = reader.readInt();
673
+
674
+ this.varbinds = [];
675
+ readVarbinds(reader, this.varbinds);
676
+};
677
+
678
+SimpleResponsePdu.prototype.initializeFromVariables = function (id, varbinds, options) {
679
+ this.id = id;
680
+ this.varbinds = varbinds;
681
+ this.options = options || {};
682
+};
683
+
684
+var GetResponsePdu = function () {
685
+ this.type = PduType.GetResponse;
686
+ GetResponsePdu.super_.apply(this, arguments);
687
+};
688
+
689
+util.inherits(GetResponsePdu, SimpleResponsePdu);
690
+
691
+GetResponsePdu.createFromBuffer = function (reader) {
692
+ var pdu = new GetResponsePdu();
693
+ pdu.initializeFromBuffer(reader);
694
+ return pdu;
695
+};
696
+
697
+GetResponsePdu.createFromVariables = function (id, varbinds, options) {
698
+ var pdu = new GetResponsePdu();
699
+ pdu.initializeFromVariables(id, varbinds, options);
700
+ return pdu;
701
+};
702
+
703
+var ReportPdu = function () {
704
+ this.type = PduType.Report;
705
+ ReportPdu.super_.apply(this, arguments);
706
+};
707
+
708
+util.inherits(ReportPdu, SimpleResponsePdu);
709
+
710
+ReportPdu.createFromBuffer = function (reader) {
711
+ var pdu = new ReportPdu();
712
+ pdu.initializeFromBuffer(reader);
713
+ return pdu;
714
+};
715
+
716
+ReportPdu.createFromVariables = function (id, varbinds, options) {
717
+ var pdu = new ReportPdu();
718
+ pdu.initializeFromVariables(id, varbinds, options);
719
+ return pdu;
720
+};
721
+
722
+var readPdu = function (reader, scoped) {
723
+ var pdu;
724
+ var contextEngineID;
725
+ var contextName;
726
+ if (scoped) {
727
+ reader.readSequence();
728
+ contextEngineID = reader.readString(ber.OctetString, true);
729
+ contextName = reader.readString();
730
+ }
731
+ var type = reader.peek();
732
+
733
+ if (type == PduType.GetResponse) {
734
+ pdu = GetResponsePdu.createFromBuffer(reader);
735
+ } else if (type == PduType.Report) {
736
+ pdu = ReportPdu.createFromBuffer(reader);
737
+ } else if (type == PduType.Trap) {
738
+ pdu = TrapPdu.createFromBuffer(reader);
739
+ } else if (type == PduType.TrapV2) {
740
+ pdu = TrapV2Pdu.createFromBuffer(reader);
741
+ } else if (type == PduType.InformRequest) {
742
+ pdu = InformRequestPdu.createFromBuffer(reader);
743
+ } else if (type == PduType.GetRequest) {
744
+ pdu = GetRequestPdu.createFromBuffer(reader);
745
+ } else if (type == PduType.SetRequest) {
746
+ pdu = SetRequestPdu.createFromBuffer(reader);
747
+ } else if (type == PduType.GetNextRequest) {
748
+ pdu = GetNextRequestPdu.createFromBuffer(reader);
749
+ } else if (type == PduType.GetBulkRequest) {
750
+ pdu = GetBulkRequestPdu.createFromBuffer(reader);
751
+ } else {
752
+ throw new ResponseInvalidError("Unknown PDU type '" + type
753
+ + "' in response");
754
+ }
755
+ if (scoped) {
756
+ pdu.contextEngineID = contextEngineID;
757
+ pdu.contextName = contextName;
758
+ }
759
+ pdu.scoped = scoped;
760
+ return pdu;
761
+};
762
+
763
+var createDiscoveryPdu = function (context) {
764
+ return GetRequestPdu.createFromVariables(_generateId(), [], {context: context});
765
+};
766
+
767
+var Authentication = {};
768
+
769
+Authentication.HMAC_BUFFER_SIZE = 1024 * 1024;
770
+Authentication.HMAC_BLOCK_SIZE = 64;
771
+Authentication.AUTHENTICATION_CODE_LENGTH = 12;
772
+Authentication.AUTH_PARAMETERS_PLACEHOLDER = Buffer.from('8182838485868788898a8b8c', 'hex');
773
+
774
+Authentication.algorithms = {};
775
+
776
+Authentication.algorithms[AuthProtocols.md5] = {
777
+ // KEY_LENGTH: 16,
778
+ CRYPTO_ALGORITHM: 'md5'
779
+};
780
+
781
+Authentication.algorithms[AuthProtocols.sha] = {
782
+ // KEY_LENGTH: 20,
783
+ CRYPTO_ALGORITHM: 'sha1'
784
+};
785
+
786
+// Adapted from RFC3414 Appendix A.2.1. Password to Key Sample Code for MD5
787
+Authentication.passwordToKey = function (authProtocol, authPasswordString, engineID) {
788
+ var hashAlgorithm;
789
+ var firstDigest;
790
+ var finalDigest;
791
+ var buf = Buffer.alloc(Authentication.HMAC_BUFFER_SIZE);
792
+ var bufOffset = 0;
793
+ var passwordIndex = 0;
794
+ var count = 0;
795
+ var password = Buffer.from(authPasswordString);
796
+ var cryptoAlgorithm = Authentication.algorithms[authProtocol].CRYPTO_ALGORITHM;
797
+
798
+ while (count < Authentication.HMAC_BUFFER_SIZE) {
799
+ for (var i = 0; i < Authentication.HMAC_BLOCK_SIZE; i++) {
800
+ buf.writeUInt8(password[passwordIndex++ % password.length], bufOffset++);
801
+ }
802
+ count += Authentication.HMAC_BLOCK_SIZE;
803
+ }
804
+ hashAlgorithm = crypto.createHash(cryptoAlgorithm);
805
+ hashAlgorithm.update(buf);
806
+ firstDigest = hashAlgorithm.digest();
807
+ // debug ("First digest: " + firstDigest.toString('hex'));
808
+
809
+ hashAlgorithm = crypto.createHash(cryptoAlgorithm);
810
+ hashAlgorithm.update(firstDigest);
811
+ hashAlgorithm.update(engineID);
812
+ hashAlgorithm.update(firstDigest);
813
+ finalDigest = hashAlgorithm.digest();
814
+ debug("Localized key: " + finalDigest.toString('hex'));
815
+
816
+ return finalDigest;
817
+};
818
+
819
+Authentication.addParametersToMessageBuffer = function (messageBuffer, authProtocol, authPassword, engineID) {
820
+ var authenticationParametersOffset;
821
+ var digestToAdd;
822
+
823
+ // clear the authenticationParameters field in message
824
+ authenticationParametersOffset = messageBuffer.indexOf(Authentication.AUTH_PARAMETERS_PLACEHOLDER);
825
+ messageBuffer.fill(0, authenticationParametersOffset, authenticationParametersOffset + Authentication.AUTHENTICATION_CODE_LENGTH);
826
+
827
+ digestToAdd = Authentication.calculateDigest(messageBuffer, authProtocol, authPassword, engineID);
828
+ digestToAdd.copy(messageBuffer, authenticationParametersOffset, 0, Authentication.AUTHENTICATION_CODE_LENGTH);
829
+ debug("Added Auth Parameters: " + digestToAdd.toString('hex'));
830
+};
831
+
832
+Authentication.isAuthentic = function (messageBuffer, authProtocol, authPassword, engineID, digestInMessage) {
833
+ var authenticationParametersOffset;
834
+ var calculatedDigest;
835
+
836
+ // clear the authenticationParameters field in message
837
+ authenticationParametersOffset = messageBuffer.indexOf(digestInMessage);
838
+ messageBuffer.fill(0, authenticationParametersOffset, authenticationParametersOffset + Authentication.AUTHENTICATION_CODE_LENGTH);
839
+
840
+ calculatedDigest = Authentication.calculateDigest(messageBuffer, authProtocol, authPassword, engineID);
841
+
842
+ // replace previously cleared authenticationParameters field in message
843
+ digestInMessage.copy(messageBuffer, authenticationParametersOffset, 0, Authentication.AUTHENTICATION_CODE_LENGTH);
844
+
845
+ debug("Digest in message: " + digestInMessage.toString('hex'));
846
+ debug("Calculated digest: " + calculatedDigest.toString('hex'));
847
+ return calculatedDigest.equals(digestInMessage, Authentication.AUTHENTICATION_CODE_LENGTH);
848
+};
849
+
850
+Authentication.calculateDigest = function (messageBuffer, authProtocol, authPassword, engineID) {
851
+ var authKey = Authentication.passwordToKey(authProtocol, authPassword, engineID);
852
+
853
+ // Adapted from RFC3147 Section 6.3.1. Processing an Outgoing Message
854
+ var hashAlgorithm;
855
+ var kIpad;
856
+ var kOpad;
857
+ var firstDigest;
858
+ var finalDigest;
859
+ var truncatedDigest;
860
+ var i;
861
+ var cryptoAlgorithm = Authentication.algorithms[authProtocol].CRYPTO_ALGORITHM;
862
+
863
+ if (authKey.length > Authentication.HMAC_BLOCK_SIZE) {
864
+ hashAlgorithm = crypto.createHash(cryptoAlgorithm);
865
+ hashAlgorithm.update(authKey);
866
+ authKey = hashAlgorithm.digest();
867
+ }
868
+
869
+ // MD(K XOR opad, MD(K XOR ipad, msg))
870
+ kIpad = Buffer.alloc(Authentication.HMAC_BLOCK_SIZE);
871
+ kOpad = Buffer.alloc(Authentication.HMAC_BLOCK_SIZE);
872
+ for (i = 0; i < authKey.length; i++) {
873
+ kIpad[i] = authKey[i] ^ 0x36;
874
+ kOpad[i] = authKey[i] ^ 0x5c;
875
+ }
876
+ kIpad.fill(0x36, authKey.length);
877
+ kOpad.fill(0x5c, authKey.length);
878
+
879
+ // inner MD
880
+ hashAlgorithm = crypto.createHash(cryptoAlgorithm);
881
+ hashAlgorithm.update(kIpad);
882
+ hashAlgorithm.update(messageBuffer);
883
+ firstDigest = hashAlgorithm.digest();
884
+ // outer MD
885
+ hashAlgorithm = crypto.createHash(cryptoAlgorithm);
886
+ hashAlgorithm.update(kOpad);
887
+ hashAlgorithm.update(firstDigest);
888
+ finalDigest = hashAlgorithm.digest();
889
+
890
+ truncatedDigest = Buffer.alloc(Authentication.AUTHENTICATION_CODE_LENGTH);
891
+ finalDigest.copy(truncatedDigest, 0, 0, Authentication.AUTHENTICATION_CODE_LENGTH);
892
+ return truncatedDigest;
893
+};
894
+
895
+var Encryption = {};
896
+
897
+Encryption.INPUT_KEY_LENGTH = 16;
898
+Encryption.DES_KEY_LENGTH = 8;
899
+Encryption.DES_BLOCK_LENGTH = 8;
900
+Encryption.CRYPTO_DES_ALGORITHM = 'des-cbc';
901
+Encryption.PRIV_PARAMETERS_PLACEHOLDER = Buffer.from('9192939495969798', 'hex');
902
+
903
+Encryption.encryptPdu = function (scopedPdu, privProtocol, privPassword, authProtocol, engineID) {
904
+ var privLocalizedKey;
905
+ var encryptionKey;
906
+ var preIv;
907
+ var salt;
908
+ var iv;
909
+ var i;
910
+ var paddedScopedPduLength;
911
+ var paddedScopedPdu;
912
+ var encryptedPdu;
913
+ var cbcProtocol = Encryption.CRYPTO_DES_ALGORITHM;
914
+
915
+ privLocalizedKey = Authentication.passwordToKey(authProtocol, privPassword, engineID);
916
+ encryptionKey = Buffer.alloc(Encryption.DES_KEY_LENGTH);
917
+ privLocalizedKey.copy(encryptionKey, 0, 0, Encryption.DES_KEY_LENGTH);
918
+ preIv = Buffer.alloc(Encryption.DES_BLOCK_LENGTH);
919
+ privLocalizedKey.copy(preIv, 0, Encryption.DES_KEY_LENGTH, Encryption.DES_KEY_LENGTH + Encryption.DES_BLOCK_LENGTH);
920
+
921
+ salt = Buffer.alloc(Encryption.DES_BLOCK_LENGTH);
922
+ // set local SNMP engine boots part of salt to 1, as we have no persistent engine state
923
+ salt.fill('00000001', 0, 4, 'hex');
924
+ // set local integer part of salt to random
925
+ salt.fill(crypto.randomBytes(4), 4, 8);
926
+ iv = Buffer.alloc(Encryption.DES_BLOCK_LENGTH);
927
+ for (i = 0; i < iv.length; i++) {
928
+ iv[i] = preIv[i] ^ salt[i];
929
+ }
930
+
931
+ if (scopedPdu.length % Encryption.DES_BLOCK_LENGTH == 0) {
932
+ paddedScopedPdu = scopedPdu;
933
+ } else {
934
+ paddedScopedPduLength = Encryption.DES_BLOCK_LENGTH * (Math.floor(scopedPdu.length / Encryption.DES_BLOCK_LENGTH) + 1);
935
+ paddedScopedPdu = Buffer.alloc(paddedScopedPduLength);
936
+ scopedPdu.copy(paddedScopedPdu, 0, 0, scopedPdu.length);
937
+ }
938
+ cipher = crypto.createCipheriv(cbcProtocol, encryptionKey, iv);
939
+ encryptedPdu = cipher.update(paddedScopedPdu);
940
+ encryptedPdu = Buffer.concat([encryptedPdu, cipher.final()]);
941
+ debug("Key: " + encryptionKey.toString('hex'));
942
+ debug("IV: " + iv.toString('hex'));
943
+ debug("Plain: " + paddedScopedPdu.toString('hex'));
944
+ debug("Encrypted: " + encryptedPdu.toString('hex'));
945
+
946
+ return {
947
+ encryptedPdu: encryptedPdu,
948
+ msgPrivacyParameters: salt
949
+ };
950
+};
951
+
952
+Encryption.decryptPdu = function (encryptedPdu, privProtocol, privParameters, privPassword, authProtocol, engineID, forceAutoPaddingDisable) {
953
+ var privLocalizedKey;
954
+ var decryptionKey;
955
+ var preIv;
956
+ var salt;
957
+ var iv;
958
+ var i;
959
+ var decryptedPdu;
960
+ var cbcProtocol = Encryption.CRYPTO_DES_ALGORITHM;
961
+ ;
962
+
963
+ privLocalizedKey = Authentication.passwordToKey(authProtocol, privPassword, engineID);
964
+ decryptionKey = Buffer.alloc(Encryption.DES_KEY_LENGTH);
965
+ privLocalizedKey.copy(decryptionKey, 0, 0, Encryption.DES_KEY_LENGTH);
966
+ preIv = Buffer.alloc(Encryption.DES_BLOCK_LENGTH);
967
+ privLocalizedKey.copy(preIv, 0, Encryption.DES_KEY_LENGTH, Encryption.DES_KEY_LENGTH + Encryption.DES_BLOCK_LENGTH);
968
+
969
+ salt = privParameters;
970
+ iv = Buffer.alloc(Encryption.DES_BLOCK_LENGTH);
971
+ for (i = 0; i < iv.length; i++) {
972
+ iv[i] = preIv[i] ^ salt[i];
973
+ }
974
+
975
+ decipher = crypto.createDecipheriv(cbcProtocol, decryptionKey, iv);
976
+ if (forceAutoPaddingDisable) {
977
+ decipher.setAutoPadding(false);
978
+ }
979
+ decryptedPdu = decipher.update(encryptedPdu);
980
+ // This try-catch is a workaround for a seemingly incorrect error condition
981
+ // - where sometimes a decrypt error is thrown with decipher.final()
982
+ // It replaces this line which should have been sufficient:
983
+ // decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
984
+ try {
985
+ decryptedPdu = Buffer.concat([decryptedPdu, decipher.final()]);
986
+ } catch (error) {
987
+ // debug("Decrypt error: " + error);
988
+ decipher = crypto.createDecipheriv(cbcProtocol, decryptionKey, iv);
989
+ decipher.setAutoPadding(false);
990
+ decryptedPdu = decipher.update(encryptedPdu);
991
+ decryptedPdu = Buffer.concat([decryptedPdu, decipher.final()]);
992
+ }
993
+ debug("Key: " + decryptionKey.toString('hex'));
994
+ debug("IV: " + iv.toString('hex'));
995
+ debug("Encrypted: " + encryptedPdu.toString('hex'));
996
+ debug("Plain: " + decryptedPdu.toString('hex'));
997
+
998
+ return decryptedPdu;
999
+
1000
+};
1001
+
1002
+Encryption.addParametersToMessageBuffer = function (messageBuffer, msgPrivacyParameters) {
1003
+ privacyParametersOffset = messageBuffer.indexOf(Encryption.PRIV_PARAMETERS_PLACEHOLDER);
1004
+ msgPrivacyParameters.copy(messageBuffer, privacyParametersOffset, 0, Encryption.DES_IV_LENGTH);
1005
+};
1006
1007
/*****************************************************************************
498
- ** Message class definitions
1008
+ ** Message class definition
1009
**/
1010
501
-var RequestMessage = function (version, community, pdu) {
502
- this.version = version;
503
- this.community = community;
504
- this.pdu = pdu;
1011
+var Message = function () {
1012
+}
1013
+
1014
+Message.prototype.getReqId = function () {
1015
+ return this.version == Version3 ? this.msgGlobalData.msgID : this.pdu.id;
1016
+};
1017
+
1018
+Message.prototype.toBuffer = function () {
1019
+ if (this.version == Version3) {
1020
+ return this.toBufferV3();
1021
+ } else {
1022
+ return this.toBufferCommunity();
1023
+ }
1024
+}
1025
+
1026
+Message.prototype.toBufferCommunity = function () {
1027
+ if (this.buffer)
1028
+ return this.buffer;
1029
+
1030
+ var writer = new ber.Writer();
1031
+
1032
+ writer.startSequence();
1033
+
1034
+ writer.writeInt(this.version);
1035
+ writer.writeString(this.community);
1036
+
1037
+ this.pdu.toBuffer(writer);
1038
+
1039
+ writer.endSequence();
1040
+
1041
+ this.buffer = writer.buffer;
1042
+
1043
+ return this.buffer;
1044
+};
1045
+
1046
+Message.prototype.toBufferV3 = function () {
1047
+ var encryptionResult;
1048
+
1049
+ if (this.buffer)
1050
+ return this.buffer;
1051
+
1052
+ var writer = new ber.Writer();
1053
+
1054
+ writer.startSequence();
1055
+
1056
+ writer.writeInt(this.version);
1057
+
1058
+ // HeaderData
1059
+ writer.startSequence();
1060
+ writer.writeInt(this.msgGlobalData.msgID);
1061
+ writer.writeInt(this.msgGlobalData.msgMaxSize);
1062
+ writer.writeByte(ber.OctetString);
1063
+ writer.writeByte(1);
1064
+ writer.writeByte(this.msgGlobalData.msgFlags);
1065
+ writer.writeInt(this.msgGlobalData.msgSecurityModel);
1066
+ writer.endSequence();
1067
+
1068
+ // msgSecurityParameters
1069
+ var msgSecurityParametersWriter = new ber.Writer();
1070
+ msgSecurityParametersWriter.startSequence();
1071
+ //msgSecurityParametersWriter.writeString (this.msgSecurityParameters.msgAuthoritativeEngineID);
1072
+ // writing a zero-length buffer fails - should fix asn1-ber for this condition
1073
+ if (this.msgSecurityParameters.msgAuthoritativeEngineID.length == 0) {
1074
+ msgSecurityParametersWriter.writeString("");
1075
+ } else {
1076
+ msgSecurityParametersWriter.writeBuffer(this.msgSecurityParameters.msgAuthoritativeEngineID, ber.OctetString);
1077
+ }
1078
+ msgSecurityParametersWriter.writeInt(this.msgSecurityParameters.msgAuthoritativeEngineBoots);
1079
+ msgSecurityParametersWriter.writeInt(this.msgSecurityParameters.msgAuthoritativeEngineTime);
1080
+ msgSecurityParametersWriter.writeString(this.msgSecurityParameters.msgUserName);
1081
+
1082
+ if (this.hasAuthentication()) {
1083
+ msgSecurityParametersWriter.writeBuffer(Authentication.AUTH_PARAMETERS_PLACEHOLDER, ber.OctetString);
1084
+ // should never happen where msgFlags has no authentication but authentication parameters still present
1085
+ } else if (this.msgSecurityParameters.msgAuthenticationParameters.length > 0) {
1086
+ msgSecurityParametersWriter.writeBuffer(this.msgSecurityParameters.msgAuthenticationParameters, ber.OctetString);
1087
+ } else {
1088
+ msgSecurityParametersWriter.writeString("");
1089
+ }
1090
+
1091
+ if (this.hasPrivacy()) {
1092
+ msgSecurityParametersWriter.writeBuffer(Encryption.PRIV_PARAMETERS_PLACEHOLDER, ber.OctetString);
1093
+ // should never happen where msgFlags has no privacy but privacy parameters still present
1094
+ } else if (this.msgSecurityParameters.msgPrivacyParameters.length > 0) {
1095
+ msgSecurityParametersWriter.writeBuffer(this.msgSecurityParameters.msgPrivacyParameters, ber.OctetString);
1096
+ } else {
1097
+ msgSecurityParametersWriter.writeString("");
1098
+ }
1099
+ msgSecurityParametersWriter.endSequence();
1100
+
1101
+ writer.writeBuffer(msgSecurityParametersWriter.buffer, ber.OctetString);
1102
+
1103
+ // ScopedPDU
1104
+ var scopedPduWriter = new ber.Writer();
1105
+ scopedPduWriter.startSequence();
1106
+ var contextEngineID = this.pdu.contextEngineID ? this.pdu.contextEngineID : this.msgSecurityParameters.msgAuthoritativeEngineID;
1107
+ if (contextEngineID.length == 0) {
1108
+ scopedPduWriter.writeString("");
1109
+ } else {
1110
+ scopedPduWriter.writeBuffer(contextEngineID, ber.OctetString);
1111
+ }
1112
+ scopedPduWriter.writeString(this.pdu.contextName);
1113
+ this.pdu.toBuffer(scopedPduWriter);
1114
+ scopedPduWriter.endSequence();
1115
+
1116
+ if (this.hasPrivacy()) {
1117
+ encryptionResult = Encryption.encryptPdu(scopedPduWriter.buffer, this.user.privProtocol, this.user.privKey, this.user.authProtocol, this.msgSecurityParameters.msgAuthoritativeEngineID);
1118
+ writer.writeBuffer(encryptionResult.encryptedPdu, ber.OctetString);
1119
+ } else {
1120
+ writer.writeBuffer(scopedPduWriter.buffer);
1121
+ }
1122
+
1123
+ writer.endSequence();
1124
+
1125
+ this.buffer = writer.buffer;
1126
+
1127
+ if (this.hasPrivacy()) {
1128
+ Encryption.addParametersToMessageBuffer(this.buffer, encryptionResult.msgPrivacyParameters);
1129
+ }
1130
+
1131
+ if (this.hasAuthentication()) {
1132
+ Authentication.addParametersToMessageBuffer(this.buffer, this.user.authProtocol, this.user.authKey,
1133
+ this.msgSecurityParameters.msgAuthoritativeEngineID);
1134
+ }
1135
+
1136
+ return this.buffer;
1137
+};
1138
+
1139
+Message.prototype.processIncomingSecurity = function (user, responseCb) {
1140
+ if (this.hasPrivacy()) {
1141
+ if (!this.decryptPdu(user, responseCb)) {
1142
+ return false;
1143
+ }
1144
+ }
1145
+
1146
+ if (this.hasAuthentication() && !this.isAuthenticationDisabled()) {
1147
+ return this.checkAuthentication(user, responseCb);
1148
+ } else {
1149
+ return true;
1150
+ }
1151
+};
1152
+
1153
+Message.prototype.decryptPdu = function (user, responseCb) {
1154
+ var decryptedPdu;
1155
+ var decryptedPduReader;
1156
+ try {
1157
+ decryptedPdu = Encryption.decryptPdu(this.encryptedPdu, user.privProtocol,
1158
+ this.msgSecurityParameters.msgPrivacyParameters, user.privKey, user.authProtocol,
1159
+ this.msgSecurityParameters.msgAuthoritativeEngineID);
1160
+ decryptedPduReader = new ber.Reader(decryptedPdu);
1161
+ this.pdu = readPdu(decryptedPduReader, true);
1162
+ return true;
1163
+ // really really occasionally the decrypt truncates a single byte
1164
+ // causing an ASN read failure in readPdu()
1165
+ // in this case, disabling auto padding decrypts the PDU correctly
1166
+ // this try-catch provides the workaround for this condition
1167
+ } catch (possibleTruncationError) {
1168
+ try {
1169
+ decryptedPdu = Encryption.decryptPdu(this.encryptedPdu, user.privProtocol,
1170
+ this.msgSecurityParameters.msgPrivacyParameters, user.privKey, user.authProtocol,
1171
+ this.msgSecurityParameters.msgAuthoritativeEngineID, true);
1172
+ decryptedPduReader = new ber.Reader(decryptedPdu);
1173
+ this.pdu = readPdu(decryptedPduReader, true);
1174
+ return true;
1175
+ } catch (error) {
1176
+ responseCb(new ResponseInvalidError("Failed to decrypt PDU: " + error));
1177
+ return false;
1178
+ }
1179
+ }
1180
+
1181
+};
1182
+
1183
+Message.prototype.checkAuthentication = function (user, responseCb) {
1184
+ if (Authentication.isAuthentic(this.buffer, user.authProtocol, user.authKey,
1185
+ this.msgSecurityParameters.msgAuthoritativeEngineID, this.msgSecurityParameters.msgAuthenticationParameters)) {
1186
+ return true;
1187
+ } else {
1188
+ responseCb(new ResponseInvalidError("Authentication digest "
1189
+ + this.msgSecurityParameters.msgAuthenticationParameters.toString('hex')
1190
+ + " received in message does not match digest "
1191
+ + Authentication.calculateDigest(buffer, user.authProtocol, user.authKey,
1192
+ this.msgSecurityParameters.msgAuthoritativeEngineID).toString('hex')
1193
+ + " calculated for message"));
1194
+ return false;
1195
+ }
1196
+
1197
+};
1198
+
1199
+Message.prototype.hasAuthentication = function () {
1200
+ return this.msgGlobalData && this.msgGlobalData.msgFlags && this.msgGlobalData.msgFlags & 1;
1201
};
1202
507
-RequestMessage.prototype.toBuffer = function () {
508
- if (this.buffer)
509
- return this.buffer;
1203
+Message.prototype.hasPrivacy = function () {
1204
+ return this.msgGlobalData && this.msgGlobalData.msgFlags && this.msgGlobalData.msgFlags & 2;
1205
+};
1206
+
1207
+Message.prototype.isReportable = function () {
1208
+ return this.msgGlobalData && this.msgGlobalData.msgFlags && this.msgGlobalData.msgFlags & 4;
1209
+};
1210
511
- var writer = new ber.Writer ();
1211
+Message.prototype.setReportable = function (flag) {
1212
+ if (this.msgGlobalData && this.msgGlobalData.msgFlags) {
1213
+ if (flag) {
1214
+ this.msgGlobalData.msgFlags = this.msgGlobalData.msgFlags | 4;
1215
+ } else {
1216
+ this.msgGlobalData.msgFlags = this.msgGlobalData.msgFlags & (255 - 4);
1217
+ }
1218
+ }
1219
+};
1220
513
- writer.startSequence ();
1221
+Message.prototype.isAuthenticationDisabled = function () {
1222
+ return this.disableAuthentication;
1223
+};
1224
515
- writer.writeInt (this.version);
516
- writer.writeString (this.community);
1225
+Message.prototype.hasAuthoritativeEngineID = function () {
1226
+ return this.msgSecurityParameters && this.msgSecurityParameters.msgAuthoritativeEngineID &&
1227
+ this.msgSecurityParameters.msgAuthoritativeEngineID != "";
1228
+};
1229
518
- this.pdu.toBuffer (writer);
1230
+Message.prototype.createReportResponseMessage = function (engine, context) {
1231
+ var user = {
1232
+ name: "",
1233
+ level: SecurityLevel.noAuthNoPriv
1234
+ };
1235
+ var responseSecurityParameters = {
1236
+ msgAuthoritativeEngineID: engine.engineID,
1237
+ msgAuthoritativeEngineBoots: engine.engineBoots,
1238
+ msgAuthoritativeEngineTime: engine.engineTime,
1239
+ msgUserName: user.name,
1240
+ msgAuthenticationParameters: "",
1241
+ msgPrivacyParameters: ""
1242
+ };
1243
+ var reportPdu = ReportPdu.createFromVariables(this.pdu.id, [], {});
1244
+ reportPdu.contextName = context;
1245
+ var responseMessage = Message.createRequestV3(user, responseSecurityParameters, reportPdu);
1246
+ responseMessage.msgGlobalData.msgID = this.msgGlobalData.msgID;
1247
+ return responseMessage;
1248
+};
1249
520
- writer.endSequence ();
1250
+Message.prototype.createResponseForRequest = function (responsePdu) {
1251
+ if (this.version == Version3) {
1252
+ return this.createV3ResponseFromRequest(responsePdu);
1253
+ } else {
1254
+ return this.createCommunityResponseFromRequest(responsePdu);
1255
+ }
1256
+};
1257
522
- this.buffer = writer.buffer;
1258
+Message.prototype.createCommunityResponseFromRequest = function (responsePdu) {
1259
+ return Message.createCommunity(this.version, this.community, responsePdu);
1260
+};
1261
524
- return this.buffer;
1262
+Message.prototype.createV3ResponseFromRequest = function (responsePdu) {
1263
+ var responseUser = {
1264
+ name: this.user.name,
1265
+ level: this.user.name,
1266
+ authProtocol: this.user.authProtocol,
1267
+ authKey: this.user.authKey,
1268
+ privProtocol: this.user.privProtocol,
1269
+ privKey: this.user.privKey
1270
+ };
1271
+ var responseSecurityParameters = {
1272
+ msgAuthoritativeEngineID: this.msgSecurityParameters.msgAuthoritativeEngineID,
1273
+ msgAuthoritativeEngineBoots: this.msgSecurityParameters.msgAuthoritativeEngineBoots,
1274
+ msgAuthoritativeEngineTime: this.msgSecurityParameters.msgAuthoritativeEngineTime,
1275
+ msgUserName: this.msgSecurityParameters.msgUserName,
1276
+ msgAuthenticationParameters: "",
1277
+ msgPrivacyParameters: ""
1278
+ };
1279
+ var responseGlobalData = {
1280
+ msgID: this.msgGlobalData.msgID,
1281
+ msgMaxSize: 65507,
1282
+ msgFlags: this.msgGlobalData.msgFlags & (255 - 4),
1283
+ msgSecurityModel: 3
1284
+ };
1285
+ return Message.createV3(responseUser, responseGlobalData, responseSecurityParameters, responsePdu);
1286
};
1287
527
-var ResponseMessage = function (buffer) {
528
- var reader = new ber.Reader (buffer);
1288
+Message.createCommunity = function (version, community, pdu) {
1289
+ var message = new Message();
1290
+
1291
+ message.version = version;
1292
+ message.community = community;
1293
+ message.pdu = pdu;
1294
+
1295
+ return message;
1296
+};
1297
530
- reader.readSequence ();
1298
+Message.createRequestV3 = function (user, msgSecurityParameters, pdu) {
1299
+ var authFlag = user.level == SecurityLevel.authNoPriv || user.level == SecurityLevel.authPriv ? 1 : 0;
1300
+ var privFlag = user.level == SecurityLevel.authPriv ? 1 : 0;
1301
+ var reportableFlag = (pdu.type == PduType.GetResponse || pdu.type == PduType.TrapV2) ? 0 : 1;
1302
+ var msgGlobalData = {
1303
+ msgID: _generateId(), // random ID
1304
+ msgMaxSize: 65507,
1305
+ msgFlags: reportableFlag * 4 | privFlag * 2 | authFlag * 1,
1306
+ msgSecurityModel: 3
1307
+ };
1308
+ return Message.createV3(user, msgGlobalData, msgSecurityParameters, pdu);
1309
+};
1310
532
- this.version = reader.readInt ();
533
- this.community = reader.readString ();
1311
+Message.createV3 = function (user, msgGlobalData, msgSecurityParameters, pdu) {
1312
+ var message = new Message();
1313
+
1314
+ message.version = 3;
1315
+ message.user = user;
1316
+ message.msgGlobalData = msgGlobalData;
1317
+ message.msgSecurityParameters = {
1318
+ msgAuthoritativeEngineID: msgSecurityParameters.msgAuthoritativeEngineID || Buffer.from(""),
1319
+ msgAuthoritativeEngineBoots: msgSecurityParameters.msgAuthoritativeEngineBoots || 0,
1320
+ msgAuthoritativeEngineTime: msgSecurityParameters.msgAuthoritativeEngineTime || 0,
1321
+ msgUserName: user.name || "",
1322
+ msgAuthenticationParameters: "",
1323
+ msgPrivacyParameters: ""
1324
+ };
1325
+ message.pdu = pdu;
1326
+
1327
+ return message;
1328
+};
1329
535
- var type = reader.peek ();
1330
+Message.createDiscoveryV3 = function (pdu) {
1331
+ var msgSecurityParameters = {
1332
+ msgAuthoritativeEngineID: Buffer.from(""),
1333
+ msgAuthoritativeEngineBoots: 0,
1334
+ msgAuthoritativeEngineTime: 0
1335
+ };
1336
+ var emptyUser = {
1337
+ name: "",
1338
+ level: SecurityLevel.noAuthNoPriv
1339
+ };
1340
+ return Message.createRequestV3(emptyUser, msgSecurityParameters, pdu);
1341
+}
1342
537
- if (type == PduType.GetResponse) {
538
- this.pdu = new GetResponsePdu (reader);
539
- } else {
540
- throw new ResponseInvalidError ("Unknown PDU type '" + type
541
- + "' in response");
542
- }
1343
+Message.createFromBuffer = function (buffer, user) {
1344
+ var reader = new ber.Reader(buffer);
1345
+ var message = new Message();
1346
+
1347
+ reader.readSequence();
1348
+
1349
+ message.version = reader.readInt();
1350
+
1351
+ if (message.version != 3) {
1352
+ message.community = reader.readString();
1353
+ message.pdu = readPdu(reader, false);
1354
+ } else {
1355
+ // HeaderData
1356
+ message.msgGlobalData = {};
1357
+ reader.readSequence();
1358
+ message.msgGlobalData.msgID = reader.readInt();
1359
+ message.msgGlobalData.msgMaxSize = reader.readInt();
1360
+ message.msgGlobalData.msgFlags = reader.readString(ber.OctetString, true)[0];
1361
+ message.msgGlobalData.msgSecurityModel = reader.readInt();
1362
+
1363
+ // msgSecurityParameters
1364
+ message.msgSecurityParameters = {};
1365
+ var msgSecurityParametersReader = new ber.Reader(reader.readString(ber.OctetString, true));
1366
+ msgSecurityParametersReader.readSequence();
1367
+ message.msgSecurityParameters.msgAuthoritativeEngineID = msgSecurityParametersReader.readString(ber.OctetString, true);
1368
+ message.msgSecurityParameters.msgAuthoritativeEngineBoots = msgSecurityParametersReader.readInt();
1369
+ message.msgSecurityParameters.msgAuthoritativeEngineTime = msgSecurityParametersReader.readInt();
1370
+ message.msgSecurityParameters.msgUserName = msgSecurityParametersReader.readString();
1371
+ message.msgSecurityParameters.msgAuthenticationParameters = Buffer.from(msgSecurityParametersReader.readString(ber.OctetString, true));
1372
+ message.msgSecurityParameters.msgPrivacyParameters = Buffer.from(msgSecurityParametersReader.readString(ber.OctetString, true));
1373
+ scopedPdu = true;
1374
+
1375
+ if (message.hasPrivacy()) {
1376
+ message.encryptedPdu = reader.readString(ber.OctetString, true);
1377
+ message.pdu = null;
1378
+ } else {
1379
+ message.pdu = readPdu(reader, true);
1380
+ }
1381
+ }
1382
+
1383
+ message.buffer = buffer;
1384
+
1385
+ return message;
1386
};
1387
1388
+
1389
+var Req = function (session, message, feedCb, responseCb, options) {
1390
+
1391
+ this.message = message;
1392
+ this.responseCb = responseCb;
1393
+ this.retries = session.retries;
1394
+ this.timeout = session.timeout;
1395
+ this.onResponse = session.onSimpleGetResponse;
1396
+ this.feedCb = feedCb;
1397
+ this.port = (options && options.port) ? options.port : session.port;
1398
+ this.context = session.context;
1399
+};
1400
+
1401
+Req.prototype.getId = function () {
1402
+ return this.message.getReqId();
1403
+};
1404
+
1405
+
1406
/*****************************************************************************
1407
** Session class definition
1408
**/
1409
549
-var Session = function (target, community, options) {
550
- this.target = target || "127.0.0.1";
551
- this.community = community || "public";
552
-
553
- this.version = (options && options.version)
554
- ? options.version
555
- : Version1;
556
-
557
- this.transport = (options && options.transport)
558
- ? options.transport
559
- : "udp4";
560
- this.port = (options && options.port )
561
- ? options.port
562
- : 161;
563
- this.trapPort = (options && options.trapPort )
564
- ? options.trapPort
565
- : 162;
566
-
567
- this.retries = (options && (options.retries || options.retries == 0))
568
- ? options.retries
569
- : 1;
570
- this.timeout = (options && options.timeout)
571
- ? options.timeout
572
- : 5000;
573
-
574
- this.sourceAddress = (options && options.sourceAddress )
575
- ? options.sourceAddress
576
- : undefined;
577
- this.sourcePort = (options && options.sourcePort )
578
- ? parseInt(options.sourcePort)
579
- : undefined;
580
-
581
- this.idBitsSize = (options && options.idBitsSize)
582
- ? parseInt(options.idBitsSize)
583
- : 32;
584
-
585
- this.reqs = {};
586
- this.reqCount = 0;
587
-
588
- this.dgram = dgram.createSocket (this.transport);
589
- this.dgram.unref();
590
-
591
- var me = this;
592
- this.dgram.on ("message", me.onMsg.bind (me));
593
- this.dgram.on ("close", me.onClose.bind (me));
594
- this.dgram.on ("error", me.onError.bind (me));
595
-
596
- if (this.sourceAddress || this.sourcePort)
597
- this.dgram.bind (this.sourcePort, this.sourceAddress);
598
-};
599
-
600
-util.inherits (Session, events.EventEmitter);
1410
+var Session = function (target, authenticator, options) {
1411
+ this.target = target || "127.0.0.1";
1412
+
1413
+ this.version = (options && options.version)
1414
+ ? options.version
1415
+ : Version1;
1416
+
1417
+ if (this.version == Version3) {
1418
+ this.user = authenticator;
1419
+ } else {
1420
+ this.community = authenticator || "public";
1421
+ }
1422
+
1423
+ this.transport = (options && options.transport)
1424
+ ? options.transport
1425
+ : "udp4";
1426
+ this.port = (options && options.port)
1427
+ ? options.port
1428
+ : 161;
1429
+ this.trapPort = (options && options.trapPort)
1430
+ ? options.trapPort
1431
+ : 162;
1432
+
1433
+ this.retries = (options && (options.retries || options.retries == 0))
1434
+ ? options.retries
1435
+ : 1;
1436
+ this.timeout = (options && options.timeout)
1437
+ ? options.timeout
1438
+ : 5000;
1439
+
1440
+ this.sourceAddress = (options && options.sourceAddress)
1441
+ ? options.sourceAddress
1442
+ : undefined;
1443
+ this.sourcePort = (options && options.sourcePort)
1444
+ ? parseInt(options.sourcePort)
1445
+ : undefined;
1446
+
1447
+ this.idBitsSize = (options && options.idBitsSize)
1448
+ ? parseInt(options.idBitsSize)
1449
+ : 32;
1450
+
1451
+ this.context = (options && options.context) ? options.context : "";
1452
+
1453
+ DEBUG = options.debug;
1454
+
1455
+ this.reqs = {};
1456
+ this.reqCount = 0;
1457
+
1458
+ this.dgram = dgram.createSocket(this.transport);
1459
+ this.dgram.unref();
1460
+
1461
+ var me = this;
1462
+ this.dgram.on("message", me.onMsg.bind(me));
1463
+ this.dgram.on("close", me.onClose.bind(me));
1464
+ this.dgram.on("error", me.onError.bind(me));
1465
+
1466
+ if (this.sourceAddress || this.sourcePort)
1467
+ this.dgram.bind(this.sourcePort, this.sourceAddress);
1468
+};
1469
+
1470
+util.inherits(Session, events.EventEmitter);
1471
1472
Session.prototype.close = function () {
603
- this.dgram.close ();
604
- return this;
1473
+ this.dgram.close();
1474
+ return this;
1475
};
1476
1477
Session.prototype.cancelRequests = function (error) {
608
- var id;
609
- for (id in this.reqs) {
610
- var req = this.reqs[id];
611
- this.unregisterRequest (req.id);
612
- req.responseCb (error);
613
- }
614
-};
615
-
616
-function _generateId (bitSize) {
617
- if (bitSize === 16) {
618
- return Math.floor(Math.random() * 10000) % 65535;
619
- }
620
- return Math.floor(Math.random() * 100000000) % 4294967295;
1478
+ var id;
1479
+ for (id in this.reqs) {
1480
+ var req = this.reqs[id];
1481
+ this.unregisterRequest(req.getId());
1482
+ req.responseCb(error);
1483
+ }
1484
+};
1485
+
1486
+function _generateId(bitSize) {
1487
+ if (bitSize === 16) {
1488
+ return Math.floor(Math.random() * 10000) % 65535;
1489
+ }
1490
+ return Math.floor(Math.random() * 100000000) % 4294967295;
1491
}
1492
1493
Session.prototype.get = function (oids, responseCb) {
624
- function feedCb (req, message) {
625
- var pdu = message.pdu;
626
- var varbinds = [];
627
-
628
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
629
- req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
630
- + "match response OIDs"));
631
- } else {
632
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
633
- if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
634
- req.responseCb (new ResponseInvalidError ("OID '"
635
- + req.message.pdu.varbinds[i].oid
636
- + "' in request at positiion '" + i + "' does not "
637
- + "match OID '" + pdu.varbinds[i].oid + "' in response "
638
- + "at position '" + i + "'"));
639
- return;
640
- } else {
641
- varbinds.push (pdu.varbinds[i]);
642
- }
643
- }
644
-
645
- req.responseCb (null, varbinds);
646
- }
647
- }
648
-
649
- var pduVarbinds = [];
650
-
651
- for (var i = 0; i < oids.length; i++) {
652
- var varbind = {
653
- oid: oids[i]
654
- };
655
- pduVarbinds.push (varbind);
656
- }
657
-
658
- this.simpleGet (GetRequestPdu, feedCb, pduVarbinds, responseCb);
659
-
660
- return this;
1494
+ function feedCb(req, message) {
1495
+ var pdu = message.pdu;
1496
+ var varbinds = [];
1497
+
1498
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1499
+ req.responseCb(new ResponseInvalidError("Requested OIDs do not "
1500
+ + "match response OIDs"));
1501
+ } else {
1502
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1503
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1504
+ req.responseCb(new ResponseInvalidError("OID '"
1505
+ + req.message.pdu.varbinds[i].oid
1506
+ + "' in request at positiion '" + i + "' does not "
1507
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
1508
+ + "at position '" + i + "'"));
1509
+ return;
1510
+ } else {
1511
+ varbinds.push(pdu.varbinds[i]);
1512
+ }
1513
+ }
1514
+
1515
+ req.responseCb(null, varbinds);
1516
+ }
1517
+ }
1518
+
1519
+ var pduVarbinds = [];
1520
+
1521
+ for (var i = 0; i < oids.length; i++) {
1522
+ var varbind = {
1523
+ oid: oids[i]
1524
+ };
1525
+ pduVarbinds.push(varbind);
1526
+ }
1527
+
1528
+ this.simpleGet(GetRequestPdu, feedCb, pduVarbinds, responseCb);
1529
+
1530
+ return this;
1531
};
1532
1533
Session.prototype.getBulk = function () {
664
- var oids, nonRepeaters, maxRepetitions, responseCb;
665
-
666
- if (arguments.length >= 4) {
667
- oids = arguments[0];
668
- nonRepeaters = arguments[1];
669
- maxRepetitions = arguments[2];
670
- responseCb = arguments[3];
671
- } else if (arguments.length >= 3) {
672
- oids = arguments[0];
673
- nonRepeaters = arguments[1];
674
- maxRepetitions = 10;
675
- responseCb = arguments[2];
676
- } else {
677
- oids = arguments[0];
678
- nonRepeaters = 0;
679
- maxRepetitions = 10;
680
- responseCb = arguments[1];
681
- }
682
-
683
- function feedCb (req, message) {
684
- var pdu = message.pdu;
685
- var varbinds = [];
686
- var i = 0;
687
-
688
- // first walk through and grab non-repeaters
689
- if (pdu.varbinds.length < nonRepeaters) {
690
- req.responseCb (new ResponseInvalidError ("Varbind count in "
691
- + "response '" + pdu.varbinds.length + "' is less than "
692
- + "non-repeaters '" + nonRepeaters + "' in request"));
693
- } else {
694
- for ( ; i < nonRepeaters; i++) {
695
- if (isVarbindError (pdu.varbinds[i])) {
696
- varbinds.push (pdu.varbinds[i]);
697
- } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
698
- pdu.varbinds[i].oid)) {
699
- req.responseCb (new ResponseInvalidError ("OID '"
700
- + req.message.pdu.varbinds[i].oid + "' in request at "
701
- + "positiion '" + i + "' does not precede "
702
- + "OID '" + pdu.varbinds[i].oid + "' in response "
703
- + "at position '" + i + "'"));
704
- return;
705
- } else {
706
- varbinds.push (pdu.varbinds[i]);
707
- }
708
- }
709
- }
710
-
711
- var repeaters = req.message.pdu.varbinds.length - nonRepeaters;
712
-
713
- // secondly walk through and grab repeaters
714
- if (pdu.varbinds.length % (repeaters)) {
715
- req.responseCb (new ResponseInvalidError ("Varbind count in "
716
- + "response '" + pdu.varbinds.length + "' is not a "
717
- + "multiple of repeaters '" + repeaters
718
- + "' plus non-repeaters '" + nonRepeaters + "' in request"));
719
- } else {
720
- while (i < pdu.varbinds.length) {
721
- for (var j = 0; j < repeaters; j++, i++) {
722
- var reqIndex = nonRepeaters + j;
723
- var respIndex = i;
724
-
725
- if (isVarbindError (pdu.varbinds[respIndex])) {
726
- if (! varbinds[reqIndex])
727
- varbinds[reqIndex] = [];
728
- varbinds[reqIndex].push (pdu.varbinds[respIndex]);
729
- } else if (! oidFollowsOid (
730
- req.message.pdu.varbinds[reqIndex].oid,
731
- pdu.varbinds[respIndex].oid)) {
732
- req.responseCb (new ResponseInvalidError ("OID '"
733
- + req.message.pdu.varbinds[reqIndex].oid
734
- + "' in request at positiion '" + (reqIndex)
735
- + "' does not precede OID '"
736
- + pdu.varbinds[respIndex].oid
737
- + "' in response at position '" + (respIndex) + "'"));
738
- return;
739
- } else {
740
- if (! varbinds[reqIndex])
741
- varbinds[reqIndex] = [];
742
- varbinds[reqIndex].push (pdu.varbinds[respIndex]);
743
- }
744
- }
745
- }
746
- }
747
-
748
- req.responseCb (null, varbinds);
749
- }
750
-
751
- var pduVarbinds = [];
752
-
753
- for (var i = 0; i < oids.length; i++) {
754
- var varbind = {
755
- oid: oids[i]
756
- };
757
- pduVarbinds.push (varbind);
758
- }
759
-
760
- var options = {
761
- nonRepeaters: nonRepeaters,
762
- maxRepetitions: maxRepetitions
763
- };
764
-
765
- this.simpleGet (GetBulkRequestPdu, feedCb, pduVarbinds, responseCb,
766
- options);
767
-
768
- return this;
1534
+ var oids, nonRepeaters, maxRepetitions, responseCb;
1535
+
1536
+ if (arguments.length >= 4) {
1537
+ oids = arguments[0];
1538
+ nonRepeaters = arguments[1];
1539
+ maxRepetitions = arguments[2];
1540
+ responseCb = arguments[3];
1541
+ } else if (arguments.length >= 3) {
1542
+ oids = arguments[0];
1543
+ nonRepeaters = arguments[1];
1544
+ maxRepetitions = 10;
1545
+ responseCb = arguments[2];
1546
+ } else {
1547
+ oids = arguments[0];
1548
+ nonRepeaters = 0;
1549
+ maxRepetitions = 10;
1550
+ responseCb = arguments[1];
1551
+ }
1552
+
1553
+ function feedCb(req, message) {
1554
+ var pdu = message.pdu;
1555
+ var varbinds = [];
1556
+ var i = 0;
1557
+
1558
+ // first walk through and grab non-repeaters
1559
+ if (pdu.varbinds.length < nonRepeaters) {
1560
+ req.responseCb(new ResponseInvalidError("Varbind count in "
1561
+ + "response '" + pdu.varbinds.length + "' is less than "
1562
+ + "non-repeaters '" + nonRepeaters + "' in request"));
1563
+ } else {
1564
+ for (; i < nonRepeaters; i++) {
1565
+ if (isVarbindError(pdu.varbinds[i])) {
1566
+ varbinds.push(pdu.varbinds[i]);
1567
+ } else if (!oidFollowsOid(req.message.pdu.varbinds[i].oid,
1568
+ pdu.varbinds[i].oid)) {
1569
+ req.responseCb(new ResponseInvalidError("OID '"
1570
+ + req.message.pdu.varbinds[i].oid + "' in request at "
1571
+ + "positiion '" + i + "' does not precede "
1572
+ + "OID '" + pdu.varbinds[i].oid + "' in response "
1573
+ + "at position '" + i + "'"));
1574
+ return;
1575
+ } else {
1576
+ varbinds.push(pdu.varbinds[i]);
1577
+ }
1578
+ }
1579
+ }
1580
+
1581
+ var repeaters = req.message.pdu.varbinds.length - nonRepeaters;
1582
+
1583
+ // secondly walk through and grab repeaters
1584
+ if (pdu.varbinds.length % (repeaters)) {
1585
+ req.responseCb(new ResponseInvalidError("Varbind count in "
1586
+ + "response '" + pdu.varbinds.length + "' is not a "
1587
+ + "multiple of repeaters '" + repeaters
1588
+ + "' plus non-repeaters '" + nonRepeaters + "' in request"));
1589
+ } else {
1590
+ while (i < pdu.varbinds.length) {
1591
+ for (var j = 0; j < repeaters; j++, i++) {
1592
+ var reqIndex = nonRepeaters + j;
1593
+ var respIndex = i;
1594
+
1595
+ if (isVarbindError(pdu.varbinds[respIndex])) {
1596
+ if (!varbinds[reqIndex])
1597
+ varbinds[reqIndex] = [];
1598
+ varbinds[reqIndex].push(pdu.varbinds[respIndex]);
1599
+ } else if (!oidFollowsOid(
1600
+ req.message.pdu.varbinds[reqIndex].oid,
1601
+ pdu.varbinds[respIndex].oid)) {
1602
+ req.responseCb(new ResponseInvalidError("OID '"
1603
+ + req.message.pdu.varbinds[reqIndex].oid
1604
+ + "' in request at positiion '" + (reqIndex)
1605
+ + "' does not precede OID '"
1606
+ + pdu.varbinds[respIndex].oid
1607
+ + "' in response at position '" + (respIndex) + "'"));
1608
+ return;
1609
+ } else {
1610
+ if (!varbinds[reqIndex])
1611
+ varbinds[reqIndex] = [];
1612
+ varbinds[reqIndex].push(pdu.varbinds[respIndex]);
1613
+ }
1614
+ }
1615
+ }
1616
+ }
1617
+
1618
+ req.responseCb(null, varbinds);
1619
+ }
1620
+
1621
+ var pduVarbinds = [];
1622
+
1623
+ for (var i = 0; i < oids.length; i++) {
1624
+ var varbind = {
1625
+ oid: oids[i]
1626
+ };
1627
+ pduVarbinds.push(varbind);
1628
+ }
1629
+
1630
+ var options = {
1631
+ nonRepeaters: nonRepeaters,
1632
+ maxRepetitions: maxRepetitions
1633
+ };
1634
+
1635
+ this.simpleGet(GetBulkRequestPdu, feedCb, pduVarbinds, responseCb,
1636
+ options);
1637
+
1638
+ return this;
1639
};
1640
1641
Session.prototype.getNext = function (oids, responseCb) {
772
- function feedCb (req, message) {
773
- var pdu = message.pdu;
774
- var varbinds = [];
775
-
776
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
777
- req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
778
- + "match response OIDs"));
779
- } else {
780
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
781
- if (isVarbindError (pdu.varbinds[i])) {
782
- varbinds.push (pdu.varbinds[i]);
783
- } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
784
- pdu.varbinds[i].oid)) {
785
- req.responseCb (new ResponseInvalidError ("OID '"
786
- + req.message.pdu.varbinds[i].oid + "' in request at "
787
- + "positiion '" + i + "' does not precede "
788
- + "OID '" + pdu.varbinds[i].oid + "' in response "
789
- + "at position '" + i + "'"));
790
- return;
791
- } else {
792
- varbinds.push (pdu.varbinds[i]);
793
- }
794
- }
795
-
796
- req.responseCb (null, varbinds);
797
- }
798
- }
799
-
800
- var pduVarbinds = [];
801
-
802
- for (var i = 0; i < oids.length; i++) {
803
- var varbind = {
804
- oid: oids[i]
805
- };
806
- pduVarbinds.push (varbind);
807
- }
808
-
809
- this.simpleGet (GetNextRequestPdu, feedCb, pduVarbinds, responseCb);
810
-
811
- return this;
1642
+ function feedCb(req, message) {
1643
+ var pdu = message.pdu;
1644
+ var varbinds = [];
1645
+
1646
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1647
+ req.responseCb(new ResponseInvalidError("Requested OIDs do not "
1648
+ + "match response OIDs"));
1649
+ } else {
1650
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1651
+ if (isVarbindError(pdu.varbinds[i])) {
1652
+ varbinds.push(pdu.varbinds[i]);
1653
+ } else if (!oidFollowsOid(req.message.pdu.varbinds[i].oid,
1654
+ pdu.varbinds[i].oid)) {
1655
+ req.responseCb(new ResponseInvalidError("OID '"
1656
+ + req.message.pdu.varbinds[i].oid + "' in request at "
1657
+ + "positiion '" + i + "' does not precede "
1658
+ + "OID '" + pdu.varbinds[i].oid + "' in response "
1659
+ + "at position '" + i + "'"));
1660
+ return;
1661
+ } else {
1662
+ varbinds.push(pdu.varbinds[i]);
1663
+ }
1664
+ }
1665
+
1666
+ req.responseCb(null, varbinds);
1667
+ }
1668
+ }
1669
+
1670
+ var pduVarbinds = [];
1671
+
1672
+ for (var i = 0; i < oids.length; i++) {
1673
+ var varbind = {
1674
+ oid: oids[i]
1675
+ };
1676
+ pduVarbinds.push(varbind);
1677
+ }
1678
+
1679
+ this.simpleGet(GetNextRequestPdu, feedCb, pduVarbinds, responseCb);
1680
+
1681
+ return this;
1682
};
1683
1684
Session.prototype.inform = function () {
815
- var typeOrOid = arguments[0];
816
- var varbinds, options = {}, responseCb;
817
-
818
- /**
819
- ** Support the following signatures:
820
- **
821
- ** typeOrOid, varbinds, options, callback
822
- ** typeOrOid, varbinds, callback
823
- ** typeOrOid, options, callback
824
- ** typeOrOid, callback
825
- **/
826
- if (arguments.length >= 4) {
827
- varbinds = arguments[1];
828
- options = arguments[2];
829
- responseCb = arguments[3];
830
- } else if (arguments.length >= 3) {
831
- if (arguments[1].constructor != Array) {
832
- varbinds = [];
833
- options = arguments[1];
834
- responseCb = arguments[2];
835
- } else {
836
- varbinds = arguments[1];
837
- responseCb = arguments[2];
838
- }
839
- } else {
840
- varbinds = [];
841
- responseCb = arguments[1];
842
- }
843
-
844
- function feedCb (req, message) {
845
- var pdu = message.pdu;
846
- var varbinds = [];
847
-
848
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
849
- req.responseCb (new ResponseInvalidError ("Inform OIDs do not "
850
- + "match response OIDs"));
851
- } else {
852
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
853
- if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
854
- req.responseCb (new ResponseInvalidError ("OID '"
855
- + req.message.pdu.varbinds[i].oid
856
- + "' in inform at positiion '" + i + "' does not "
857
- + "match OID '" + pdu.varbinds[i].oid + "' in response "
858
- + "at position '" + i + "'"));
859
- return;
860
- } else {
861
- varbinds.push (pdu.varbinds[i]);
862
- }
863
- }
864
-
865
- req.responseCb (null, varbinds);
866
- }
867
- }
868
-
869
- if (typeof typeOrOid != "string")
870
- typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
871
-
872
- var pduVarbinds = [
873
- {
874
- oid: "1.3.6.1.2.1.1.3.0",
875
- type: ObjectType.TimeTicks,
876
- value: options.upTime || Math.floor (process.uptime () * 100)
877
- },
878
- {
879
- oid: "1.3.6.1.6.3.1.1.4.1.0",
880
- type: ObjectType.OID,
881
- value: typeOrOid
882
- }
883
- ];
884
-
885
- for (var i = 0; i < varbinds.length; i++) {
886
- var varbind = {
887
- oid: varbinds[i].oid,
888
- type: varbinds[i].type,
889
- value: varbinds[i].value
890
- };
891
- pduVarbinds.push (varbind);
892
- }
893
-
894
- options.port = this.trapPort;
895
-
896
- this.simpleGet (InformRequestPdu, feedCb, pduVarbinds, responseCb, options);
897
-
898
- return this;
1685
+ var typeOrOid = arguments[0];
1686
+ var varbinds, options = {}, responseCb;
1687
+
1688
+ /**
1689
+ ** Support the following signatures:
1690
+ **
1691
+ ** typeOrOid, varbinds, options, callback
1692
+ ** typeOrOid, varbinds, callback
1693
+ ** typeOrOid, options, callback
1694
+ ** typeOrOid, callback
1695
+ **/
1696
+ if (arguments.length >= 4) {
1697
+ varbinds = arguments[1];
1698
+ options = arguments[2];
1699
+ responseCb = arguments[3];
1700
+ } else if (arguments.length >= 3) {
1701
+ if (arguments[1].constructor != Array) {
1702
+ varbinds = [];
1703
+ options = arguments[1];
1704
+ responseCb = arguments[2];
1705
+ } else {
1706
+ varbinds = arguments[1];
1707
+ responseCb = arguments[2];
1708
+ }
1709
+ } else {
1710
+ varbinds = [];
1711
+ responseCb = arguments[1];
1712
+ }
1713
+
1714
+ if (this.version == Version1) {
1715
+ responseCb(new RequestInvalidError("Inform not allowed for SNMPv1"));
1716
+ return;
1717
+ }
1718
+
1719
+ function feedCb(req, message) {
1720
+ var pdu = message.pdu;
1721
+ var varbinds = [];
1722
+
1723
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1724
+ req.responseCb(new ResponseInvalidError("Inform OIDs do not "
1725
+ + "match response OIDs"));
1726
+ } else {
1727
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1728
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1729
+ req.responseCb(new ResponseInvalidError("OID '"
1730
+ + req.message.pdu.varbinds[i].oid
1731
+ + "' in inform at positiion '" + i + "' does not "
1732
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
1733
+ + "at position '" + i + "'"));
1734
+ return;
1735
+ } else {
1736
+ varbinds.push(pdu.varbinds[i]);
1737
+ }
1738
+ }
1739
+
1740
+ req.responseCb(null, varbinds);
1741
+ }
1742
+ }
1743
+
1744
+ if (typeof typeOrOid != "string")
1745
+ typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
1746
+
1747
+ var pduVarbinds = [
1748
+ {
1749
+ oid: "1.3.6.1.2.1.1.3.0",
1750
+ type: ObjectType.TimeTicks,
1751
+ value: options.upTime || Math.floor(process.uptime() * 100)
1752
+ },
1753
+ {
1754
+ oid: "1.3.6.1.6.3.1.1.4.1.0",
1755
+ type: ObjectType.OID,
1756
+ value: typeOrOid
1757
+ }
1758
+ ];
1759
+
1760
+ for (var i = 0; i < varbinds.length; i++) {
1761
+ var varbind = {
1762
+ oid: varbinds[i].oid,
1763
+ type: varbinds[i].type,
1764
+ value: varbinds[i].value
1765
+ };
1766
+ pduVarbinds.push(varbind);
1767
+ }
1768
+
1769
+ options.port = this.trapPort;
1770
+
1771
+ this.simpleGet(InformRequestPdu, feedCb, pduVarbinds, responseCb, options);
1772
+
1773
+ return this;
1774
};
1775
1776
Session.prototype.onClose = function () {
902
- this.cancelRequests (new Error ("Socket forcibly closed"));
903
- this.emit ("close");
1777
+ this.cancelRequests(new Error("Socket forcibly closed"));
1778
+ this.emit("close");
1779
};
1780
1781
Session.prototype.onError = function (error) {
907
- this.emit (error);
908
-};
909
-
910
-Session.prototype.onMsg = function (buffer, remote) {
911
- try {
912
- var message = new ResponseMessage (buffer);
913
-
914
- var req = this.unregisterRequest (message.pdu.id);
915
- if (! req)
916
- return;
917
-
918
- try {
919
- if (message.version != req.message.version) {
920
- req.responseCb (new ResponseInvalidError ("Version in request '"
921
- + req.message.version + "' does not match version in "
922
- + "response '" + message.version));
923
- } else if (message.community != req.message.community) {
924
- req.responseCb (new ResponseInvalidError ("Community '"
925
- + req.message.community + "' in request does not match "
926
- + "community '" + message.community + "' in response"));
927
- } else if (message.pdu.type == PduType.GetResponse) {
928
- req.onResponse (req, message);
929
- } else {
930
- req.responseCb (new ResponseInvalidError ("Unknown PDU type '"
931
- + message.pdu.type + "' in response"));
932
- }
933
- } catch (error) {
934
- req.responseCb (error);
935
- }
936
- } catch (error) {
937
- this.emit("error", error);
938
- }
1782
+ this.emit(error);
1783
+};
1784
+
1785
+Session.prototype.onMsg = function (buffer) {
1786
+ try {
1787
+ var message = Message.createFromBuffer(buffer);
1788
+
1789
+ var req = this.unregisterRequest(message.getReqId());
1790
+ if (!req)
1791
+ return;
1792
+
1793
+ if (!message.processIncomingSecurity(this.user, req.responseCb))
1794
+ return;
1795
+
1796
+ try {
1797
+ if (message.version != req.message.version) {
1798
+ req.responseCb(new ResponseInvalidError("Version in request '"
1799
+ + req.message.version + "' does not match version in "
1800
+ + "response '" + message.version + "'"));
1801
+ } else if (message.community != req.message.community) {
1802
+ req.responseCb(new ResponseInvalidError("Community '"
1803
+ + req.message.community + "' in request does not match "
1804
+ + "community '" + message.community + "' in response"));
1805
+ } else if (message.pdu.type == PduType.GetResponse) {
1806
+ req.onResponse(req, message);
1807
+ } else if (message.pdu.type == PduType.Report) {
1808
+ if (!req.originalPdu) {
1809
+ req.responseCb(new ResponseInvalidError("Unexpected Report PDU"));
1810
+ return;
1811
+ }
1812
+ this.msgSecurityParameters = {
1813
+ msgAuthoritativeEngineID: message.msgSecurityParameters.msgAuthoritativeEngineID,
1814
+ msgAuthoritativeEngineBoots: message.msgSecurityParameters.msgAuthoritativeEngineBoots,
1815
+ msgAuthoritativeEngineTime: message.msgSecurityParameters.msgAuthoritativeEngineTime
1816
+ };
1817
+ req.originalPdu.contextName = this.context;
1818
+ this.sendV3Req(req.originalPdu, req.feedCb, req.responseCb, req.options, req.port);
1819
+ } else {
1820
+ req.responseCb(new ResponseInvalidError("Unknown PDU type '"
1821
+ + message.pdu.type + "' in response"));
1822
+ }
1823
+ } catch (error) {
1824
+ req.responseCb(error);
1825
+ }
1826
+ } catch (error) {
1827
+ this.emit("error", error);
1828
+ }
1829
};
1830
1831
Session.prototype.onSimpleGetResponse = function (req, message) {
942
- var pdu = message.pdu;
943
-
944
- if (pdu.errorStatus > 0) {
945
- var statusString = ErrorStatus[pdu.errorStatus]
946
- || ErrorStatus.GeneralError;
947
- var statusCode = ErrorStatus[statusString]
948
- || ErrorStatus[ErrorStatus.GeneralError];
949
-
950
- if (pdu.errorIndex <= 0 || pdu.errorIndex > pdu.varbinds.length) {
951
- req.responseCb (new RequestFailedError (statusString, statusCode));
952
- } else {
953
- var oid = pdu.varbinds[pdu.errorIndex - 1].oid;
954
- var error = new RequestFailedError (statusString + ": " + oid,
955
- statusCode);
956
- req.responseCb (error);
957
- }
958
- } else {
959
- req.feedCb (req, message);
960
- }
1832
+ var pdu = message.pdu;
1833
+
1834
+ if (pdu.errorStatus > 0) {
1835
+ var statusString = ErrorStatus[pdu.errorStatus]
1836
+ || ErrorStatus.GeneralError;
1837
+ var statusCode = ErrorStatus[statusString]
1838
+ || ErrorStatus[ErrorStatus.GeneralError];
1839
+
1840
+ if (pdu.errorIndex <= 0 || pdu.errorIndex > pdu.varbinds.length) {
1841
+ req.responseCb(new RequestFailedError(statusString, statusCode));
1842
+ } else {
1843
+ var oid = pdu.varbinds[pdu.errorIndex - 1].oid;
1844
+ var error = new RequestFailedError(statusString + ": " + oid,
1845
+ statusCode);
1846
+ req.responseCb(error);
1847
+ }
1848
+ } else {
1849
+ req.feedCb(req, message);
1850
+ }
1851
};
1852
1853
Session.prototype.registerRequest = function (req) {
964
- if (! this.reqs[req.id]) {
965
- this.reqs[req.id] = req;
966
- if (this.reqCount <= 0)
967
- this.dgram.ref();
968
- this.reqCount++;
969
- }
970
- var me = this;
971
- req.timer = setTimeout (function () {
972
- if (req.retries-- > 0) {
973
- me.send (req);
974
- } else {
975
- me.unregisterRequest (req.id);
976
- req.responseCb (new RequestTimedOutError (
977
- "Request timed out"));
978
- }
979
- }, req.timeout);
1854
+ if (!this.reqs[req.getId()]) {
1855
+ this.reqs[req.getId()] = req;
1856
+ if (this.reqCount <= 0)
1857
+ this.dgram.ref();
1858
+ this.reqCount++;
1859
+ }
1860
+ var me = this;
1861
+ req.timer = setTimeout(function () {
1862
+ if (req.retries-- > 0) {
1863
+ me.send(req);
1864
+ } else {
1865
+ me.unregisterRequest(req.getId());
1866
+ req.responseCb(new RequestTimedOutError(
1867
+ "Request timed out"));
1868
+ }
1869
+ }, req.timeout);
1870
};
1871
1872
Session.prototype.send = function (req, noWait) {
983
- try {
984
- var me = this;
985
-
986
- var buffer = req.message.toBuffer ();
987
-
988
- this.dgram.send (buffer, 0, buffer.length, req.port, this.target,
989
- function (error, bytes) {
990
- if (error) {
991
- req.responseCb (error);
992
- } else {
993
- if (noWait) {
994
- req.responseCb (null);
995
- } else {
996
- me.registerRequest (req);
997
- }
998
- }
999
- });
1000
- } catch (error) {
1001
- req.responseCb (error);
1002
- }
1003
-
1004
- return this;
1873
+ try {
1874
+ var me = this;
1875
+
1876
+ var buffer = req.message.toBuffer();
1877
+
1878
+ this.dgram.send(buffer, 0, buffer.length, req.port, this.target,
1879
+ function (error, bytes) {
1880
+ if (error) {
1881
+ req.responseCb(error);
1882
+ } else {
1883
+ if (noWait) {
1884
+ req.responseCb(null);
1885
+ } else {
1886
+ me.registerRequest(req);
1887
+ }
1888
+ }
1889
+ });
1890
+ } catch (error) {
1891
+ req.responseCb(error);
1892
+ }
1893
+
1894
+ return this;
1895
};
1896
1897
Session.prototype.set = function (varbinds, responseCb) {
1008
- function feedCb (req, message) {
1009
- var pdu = message.pdu;
1010
- var varbinds = [];
1011
-
1012
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1013
- req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
1014
- + "match response OIDs"));
1015
- } else {
1016
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1017
- if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1018
- req.responseCb (new ResponseInvalidError ("OID '"
1019
- + req.message.pdu.varbinds[i].oid
1020
- + "' in request at positiion '" + i + "' does not "
1021
- + "match OID '" + pdu.varbinds[i].oid + "' in response "
1022
- + "at position '" + i + "'"));
1023
- return;
1024
- } else {
1025
- varbinds.push (pdu.varbinds[i]);
1026
- }
1027
- }
1028
-
1029
- req.responseCb (null, varbinds);
1030
- }
1031
- }
1032
-
1033
- var pduVarbinds = [];
1034
-
1035
- for (var i = 0; i < varbinds.length; i++) {
1036
- var varbind = {
1037
- oid: varbinds[i].oid,
1038
- type: varbinds[i].type,
1039
- value: varbinds[i].value
1040
- };
1041
- pduVarbinds.push (varbind);
1042
- }
1043
-
1044
- this.simpleGet (SetRequestPdu, feedCb, pduVarbinds, responseCb);
1045
-
1046
- return this;
1898
+ function feedCb(req, message) {
1899
+ var pdu = message.pdu;
1900
+ var varbinds = [];
1901
+
1902
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1903
+ req.responseCb(new ResponseInvalidError("Requested OIDs do not "
1904
+ + "match response OIDs"));
1905
+ } else {
1906
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1907
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1908
+ req.responseCb(new ResponseInvalidError("OID '"
1909
+ + req.message.pdu.varbinds[i].oid
1910
+ + "' in request at positiion '" + i + "' does not "
1911
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
1912
+ + "at position '" + i + "'"));
1913
+ return;
1914
+ } else {
1915
+ varbinds.push(pdu.varbinds[i]);
1916
+ }
1917
+ }
1918
+
1919
+ req.responseCb(null, varbinds);
1920
+ }
1921
+ }
1922
+
1923
+ var pduVarbinds = [];
1924
+
1925
+ for (var i = 0; i < varbinds.length; i++) {
1926
+ var varbind = {
1927
+ oid: varbinds[i].oid,
1928
+ type: varbinds[i].type,
1929
+ value: varbinds[i].value
1930
+ };
1931
+ pduVarbinds.push(varbind);
1932
+ }
1933
+
1934
+ this.simpleGet(SetRequestPdu, feedCb, pduVarbinds, responseCb);
1935
+
1936
+ return this;
1937
};
1938
1939
Session.prototype.simpleGet = function (pduClass, feedCb, varbinds,
1050
- responseCb, options) {
1051
- var req = {};
1052
-
1053
- try {
1054
- var id = _generateId (this.idBitsSize);
1055
- var pdu = new pduClass (id, varbinds, options);
1056
- var message = new RequestMessage (this.version, this.community, pdu);
1057
-
1058
- req = {
1059
- id: id,
1060
- message: message,
1061
- responseCb: responseCb,
1062
- retries: this.retries,
1063
- timeout: this.timeout,
1064
- onResponse: this.onSimpleGetResponse,
1065
- feedCb: feedCb,
1066
- port: (options && options.port) ? options.port : this.port
1067
- };
1068
-
1069
- this.send (req);
1070
- } catch (error) {
1071
- if (req.responseCb)
1072
- req.responseCb (error);
1073
- }
1074
-};
1075
-
1076
-function subtreeCb (req, varbinds) {
1077
- var done = 0;
1078
-
1079
- for (var i = varbinds.length; i > 0; i--) {
1080
- if (! oidInSubtree (req.baseOid, varbinds[i - 1].oid)) {
1081
- done = 1;
1082
- varbinds.pop ();
1083
- }
1084
- }
1085
-
1086
- if (varbinds.length > 0)
1087
- req.feedCb (varbinds);
1088
-
1089
- if (done)
1090
- return true;
1940
+ responseCb, options) {
1941
+ try {
1942
+ var id = _generateId(this.idBitsSize);
1943
+ var pdu = SimplePdu.createFromVariables(pduClass, id, varbinds, options);
1944
+ var message;
1945
+ var req;
1946
+
1947
+ if (this.version == Version3) {
1948
+ if (this.msgSecurityParameters) {
1949
+ this.sendV3Req(pdu, feedCb, responseCb, options, this.port);
1950
+ } else {
1951
+ // SNMPv3 discovery
1952
+ var discoveryPdu = createDiscoveryPdu(this.context);
1953
+ var discoveryMessage = Message.createDiscoveryV3(discoveryPdu);
1954
+ var discoveryReq = new Req(this, discoveryMessage, feedCb, responseCb, options);
1955
+ discoveryReq.originalPdu = pdu;
1956
+ this.send(discoveryReq);
1957
+ }
1958
+ } else {
1959
+ message = Message.createCommunity(this.version, this.community, pdu);
1960
+ req = new Req(this, message, feedCb, responseCb, options);
1961
+ this.send(req);
1962
+ }
1963
+ } catch (error) {
1964
+ if (responseCb)
1965
+ responseCb(error);
1966
+ }
1967
}
1968
1093
-Session.prototype.subtree = function () {
1094
- var me = this;
1095
- var oid = arguments[0];
1096
- var maxRepetitions, feedCb, doneCb;
1097
-
1098
- if (arguments.length < 4) {
1099
- maxRepetitions = 20;
1100
- feedCb = arguments[1];
1101
- doneCb = arguments[2];
1102
- } else {
1103
- maxRepetitions = arguments[1];
1104
- feedCb = arguments[2];
1105
- doneCb = arguments[3];
1106
- }
1107
-
1108
- var req = {
1109
- feedCb: feedCb,
1110
- doneCb: doneCb,
1111
- maxRepetitions: maxRepetitions,
1112
- baseOid: oid
1113
- };
1114
-
1115
- this.walk (oid, maxRepetitions, subtreeCb.bind (me, req), doneCb);
1116
-
1117
- return this;
1118
-};
1119
-
1120
-function tableColumnsResponseCb (req, error) {
1121
- if (error) {
1122
- req.responseCb (error);
1123
- } else if (req.error) {
1124
- req.responseCb (req.error);
1125
- } else {
1126
- if (req.columns.length > 0) {
1127
- var column = req.columns.pop ();
1128
- var me = this;
1129
- this.subtree (req.rowOid + column, req.maxRepetitions,
1130
- tableColumnsFeedCb.bind (me, req),
1131
- tableColumnsResponseCb.bind (me, req));
1132
- } else {
1133
- req.responseCb (null, req.table);
1134
- }
1135
- }
1969
+function subtreeCb(req, varbinds) {
1970
+ var done = 0;
1971
+
1972
+ for (var i = varbinds.length; i > 0; i--) {
1973
+ if (!oidInSubtree(req.baseOid, varbinds[i - 1].oid)) {
1974
+ done = 1;
1975
+ varbinds.pop();
1976
+ }
1977
+ }
1978
+
1979
+ if (varbinds.length > 0)
1980
+ req.feedCb(varbinds);
1981
+
1982
+ if (done)
1983
+ return true;
1984
+}
1985
+
1986
+Session.prototype.subtree = function () {
1987
+ var me = this;
1988
+ var oid = arguments[0];
1989
+ var maxRepetitions, feedCb, doneCb;
1990
+
1991
+ if (arguments.length < 4) {
1992
+ maxRepetitions = 20;
1993
+ feedCb = arguments[1];
1994
+ doneCb = arguments[2];
1995
+ } else {
1996
+ maxRepetitions = arguments[1];
1997
+ feedCb = arguments[2];
1998
+ doneCb = arguments[3];
1999
+ }
2000
+
2001
+ var req = {
2002
+ feedCb: feedCb,
2003
+ doneCb: doneCb,
2004
+ maxRepetitions: maxRepetitions,
2005
+ baseOid: oid
2006
+ };
2007
+
2008
+ this.walk(oid, maxRepetitions, subtreeCb.bind(me, req), doneCb);
2009
+
2010
+ return this;
2011
+};
2012
+
2013
+function tableColumnsResponseCb(req, error) {
2014
+ if (error) {
2015
+ req.responseCb(error);
2016
+ } else if (req.error) {
2017
+ req.responseCb(req.error);
2018
+ } else {
2019
+ if (req.columns.length > 0) {
2020
+ var column = req.columns.pop();
2021
+ var me = this;
2022
+ this.subtree(req.rowOid + column, req.maxRepetitions,
2023
+ tableColumnsFeedCb.bind(me, req),
2024
+ tableColumnsResponseCb.bind(me, req));
2025
+ } else {
2026
+ req.responseCb(null, req.table);
2027
+ }
2028
+ }
2029
}
2030
1138
-function tableColumnsFeedCb (req, varbinds) {
1139
- for (var i = 0; i < varbinds.length; i++) {
1140
- if (isVarbindError (varbinds[i])) {
1141
- req.error = new RequestFailedError (varbindError (varbind[i]));
1142
- return true;
1143
- }
1144
-
1145
- var oid = varbinds[i].oid.replace (req.rowOid, "");
1146
- if (oid && oid != varbinds[i].oid) {
1147
- var match = oid.match (/^(\d+)\.(.+)$/);
1148
- if (match && match[1] > 0) {
1149
- if (! req.table[match[2]])
1150
- req.table[match[2]] = {};
1151
- req.table[match[2]][match[1]] = varbinds[i].value;
1152
- }
1153
- }
1154
- }
2031
+function tableColumnsFeedCb(req, varbinds) {
2032
+ for (var i = 0; i < varbinds.length; i++) {
2033
+ if (isVarbindError(varbinds[i])) {
2034
+ req.error = new RequestFailedError(varbindError(varbind[i]));
2035
+ return true;
2036
+ }
2037
+
2038
+ var oid = varbinds[i].oid.replace(req.rowOid, "");
2039
+ if (oid && oid != varbinds[i].oid) {
2040
+ var match = oid.match(/^(\d+)\.(.+)$/);
2041
+ if (match && match[1] > 0) {
2042
+ if (!req.table[match[2]])
2043
+ req.table[match[2]] = {};
2044
+ req.table[match[2]][match[1]] = varbinds[i].value;
2045
+ }
2046
+ }
2047
+ }
2048
}
2049
2050
Session.prototype.tableColumns = function () {
1158
- var me = this;
1159
-
1160
- var oid = arguments[0];
1161
- var columns = arguments[1];
1162
- var maxRepetitions, responseCb;
1163
-
1164
- if (arguments.length < 4) {
1165
- responseCb = arguments[2];
1166
- maxRepetitions = 20;
1167
- } else {
1168
- maxRepetitions = arguments[2];
1169
- responseCb = arguments[3];
1170
- }
1171
-
1172
- var req = {
1173
- responseCb: responseCb,
1174
- maxRepetitions: maxRepetitions,
1175
- baseOid: oid,
1176
- rowOid: oid + ".1.",
1177
- columns: columns.slice(0),
1178
- table: {}
1179
- };
1180
-
1181
- if (req.columns.length > 0) {
1182
- var column = req.columns.pop ();
1183
- this.subtree (req.rowOid + column, maxRepetitions,
1184
- tableColumnsFeedCb.bind (me, req),
1185
- tableColumnsResponseCb.bind (me, req));
1186
- }
1187
-
1188
- return this;
1189
-};
1190
-
1191
-function tableResponseCb (req, error) {
1192
- if (error)
1193
- req.responseCb (error);
1194
- else if (req.error)
1195
- req.responseCb (req.error);
1196
- else
1197
- req.responseCb (null, req.table);
2051
+ var me = this;
2052
+
2053
+ var oid = arguments[0];
2054
+ var columns = arguments[1];
2055
+ var maxRepetitions, responseCb;
2056
+
2057
+ if (arguments.length < 4) {
2058
+ responseCb = arguments[2];
2059
+ maxRepetitions = 20;
2060
+ } else {
2061
+ maxRepetitions = arguments[2];
2062
+ responseCb = arguments[3];
2063
+ }
2064
+
2065
+ var req = {
2066
+ responseCb: responseCb,
2067
+ maxRepetitions: maxRepetitions,
2068
+ baseOid: oid,
2069
+ rowOid: oid + ".1.",
2070
+ columns: columns.slice(0),
2071
+ table: {}
2072
+ };
2073
+
2074
+ if (req.columns.length > 0) {
2075
+ var column = req.columns.pop();
2076
+ this.subtree(req.rowOid + column, maxRepetitions,
2077
+ tableColumnsFeedCb.bind(me, req),
2078
+ tableColumnsResponseCb.bind(me, req));
2079
+ }
2080
+
2081
+ return this;
2082
+};
2083
+
2084
+function tableResponseCb(req, error) {
2085
+ if (error)
2086
+ req.responseCb(error);
2087
+ else if (req.error)
2088
+ req.responseCb(req.error);
2089
+ else
2090
+ req.responseCb(null, req.table);
2091
}
2092
1200
-function tableFeedCb (req, varbinds) {
1201
- for (var i = 0; i < varbinds.length; i++) {
1202
- if (isVarbindError (varbinds[i])) {
1203
- req.error = new RequestFailedError (varbindError (varbind[i]));
1204
- return true;
1205
- }
1206
-
1207
- var oid = varbinds[i].oid.replace (req.rowOid, "");
1208
- if (oid && oid != varbinds[i].oid) {
1209
- var match = oid.match (/^(\d+)\.(.+)$/);
1210
- if (match && match[1] > 0) {
1211
- if (! req.table[match[2]])
1212
- req.table[match[2]] = {};
1213
- req.table[match[2]][match[1]] = varbinds[i].value;
1214
- }
1215
- }
1216
- }
2093
+function tableFeedCb(req, varbinds) {
2094
+ for (var i = 0; i < varbinds.length; i++) {
2095
+ if (isVarbindError(varbinds[i])) {
2096
+ req.error = new RequestFailedError(varbindError(varbind[i]));
2097
+ return true;
2098
+ }
2099
+
2100
+ var oid = varbinds[i].oid.replace(req.rowOid, "");
2101
+ if (oid && oid != varbinds[i].oid) {
2102
+ var match = oid.match(/^(\d+)\.(.+)$/);
2103
+ if (match && match[1] > 0) {
2104
+ if (!req.table[match[2]])
2105
+ req.table[match[2]] = {};
2106
+ req.table[match[2]][match[1]] = varbinds[i].value;
2107
+ }
2108
+ }
2109
+ }
2110
}
2111
2112
Session.prototype.table = function () {
1220
- var me = this;
2113
+ var me = this;
2114
+
2115
+ var oid = arguments[0];
2116
+ var maxRepetitions, responseCb;
2117
+
2118
+ if (arguments.length < 3) {
2119
+ responseCb = arguments[1];
2120
+ maxRepetitions = 20;
2121
+ } else {
2122
+ maxRepetitions = arguments[1];
2123
+ responseCb = arguments[2];
2124
+ }
2125
+
2126
+ var req = {
2127
+ responseCb: responseCb,
2128
+ maxRepetitions: maxRepetitions,
2129
+ baseOid: oid,
2130
+ rowOid: oid + ".1.",
2131
+ table: {}
2132
+ };
2133
+
2134
+ this.subtree(oid, maxRepetitions, tableFeedCb.bind(me, req),
2135
+ tableResponseCb.bind(me, req));
2136
+
2137
+ return this;
2138
+};
2139
1222
- var oid = arguments[0];
1223
- var maxRepetitions, responseCb;
2140
+Session.prototype.trap = function () {
2141
+ var req = {};
2142
+
2143
+ try {
2144
+ var typeOrOid = arguments[0];
2145
+ var varbinds, options = {}, responseCb;
2146
+ var message;
2147
+
2148
+ /**
2149
+ ** Support the following signatures:
2150
+ **
2151
+ ** typeOrOid, varbinds, options, callback
2152
+ ** typeOrOid, varbinds, agentAddr, callback
2153
+ ** typeOrOid, varbinds, callback
2154
+ ** typeOrOid, agentAddr, callback
2155
+ ** typeOrOid, options, callback
2156
+ ** typeOrOid, callback
2157
+ **/
2158
+ if (arguments.length >= 4) {
2159
+ varbinds = arguments[1];
2160
+ if (typeof arguments[2] == "string") {
2161
+ options.agentAddr = arguments[2];
2162
+ } else if (arguments[2].constructor != Array) {
2163
+ options = arguments[2];
2164
+ }
2165
+ responseCb = arguments[3];
2166
+ } else if (arguments.length >= 3) {
2167
+ if (typeof arguments[1] == "string") {
2168
+ varbinds = [];
2169
+ options.agentAddr = arguments[1];
2170
+ } else if (arguments[1].constructor != Array) {
2171
+ varbinds = [];
2172
+ options = arguments[1];
2173
+ } else {
2174
+ varbinds = arguments[1];
2175
+ agentAddr = null;
2176
+ }
2177
+ responseCb = arguments[2];
2178
+ } else {
2179
+ varbinds = [];
2180
+ responseCb = arguments[1];
2181
+ }
2182
+
2183
+ var pdu, pduVarbinds = [];
2184
+
2185
+ for (var i = 0; i < varbinds.length; i++) {
2186
+ var varbind = {
2187
+ oid: varbinds[i].oid,
2188
+ type: varbinds[i].type,
2189
+ value: varbinds[i].value
2190
+ };
2191
+ pduVarbinds.push(varbind);
2192
+ }
2193
+
2194
+ var id = _generateId(this.idBitsSize);
2195
+
2196
+ if (this.version == Version2c || this.version == Version3) {
2197
+ if (typeof typeOrOid != "string")
2198
+ typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
2199
+
2200
+ pduVarbinds.unshift(
2201
+ {
2202
+ oid: "1.3.6.1.2.1.1.3.0",
2203
+ type: ObjectType.TimeTicks,
2204
+ value: options.upTime || Math.floor(process.uptime() * 100)
2205
+ },
2206
+ {
2207
+ oid: "1.3.6.1.6.3.1.1.4.1.0",
2208
+ type: ObjectType.OID,
2209
+ value: typeOrOid
2210
+ }
2211
+ );
2212
+
2213
+ pdu = TrapV2Pdu.createFromVariables(id, pduVarbinds, options);
2214
+ } else {
2215
+ pdu = TrapPdu.createFromVariables(typeOrOid, pduVarbinds, options);
2216
+ }
2217
+
2218
+ if (this.version == Version3) {
2219
+ var msgSecurityParameters = {
2220
+ msgAuthoritativeEngineID: this.user.engineID,
2221
+ msgAuthoritativeEngineBoots: 0,
2222
+ msgAuthoritativeEngineTime: 0
2223
+ };
2224
+ message = Message.createRequestV3(this.user, msgSecurityParameters, pdu);
2225
+ } else {
2226
+ message = Message.createCommunity(this.version, this.community, pdu);
2227
+ }
2228
+
2229
+ req = {
2230
+ id: id,
2231
+ message: message,
2232
+ responseCb: responseCb,
2233
+ port: this.trapPort
2234
+ };
2235
+
2236
+ this.send(req, true);
2237
+ } catch (error) {
2238
+ if (req.responseCb)
2239
+ req.responseCb(error);
2240
+ }
2241
+
2242
+ return this;
2243
+};
2244
1225
- if (arguments.length < 3) {
1226
- responseCb = arguments[1];
1227
- maxRepetitions = 20;
1228
- } else {
1229
- maxRepetitions = arguments[1];
1230
- responseCb = arguments[2];
1231
- }
2245
+Session.prototype.unregisterRequest = function (id) {
2246
+ var req = this.reqs[id];
2247
+ if (req) {
2248
+ delete this.reqs[id];
2249
+ clearTimeout(req.timer);
2250
+ delete req.timer;
2251
+ this.reqCount--;
2252
+ if (this.reqCount <= 0)
2253
+ this.dgram.unref();
2254
+ return req;
2255
+ } else {
2256
+ return null;
2257
+ }
2258
+};
2259
1233
- var req = {
1234
- responseCb: responseCb,
1235
- maxRepetitions: maxRepetitions,
1236
- baseOid: oid,
1237
- rowOid: oid + ".1.",
1238
- table: {}
1239
- };
2260
+function walkCb(req, error, varbinds) {
2261
+ var done = 0;
2262
+ var oid;
2263
+
2264
+ if (error) {
2265
+ if (error instanceof RequestFailedError) {
2266
+ if (error.status != ErrorStatus.NoSuchName) {
2267
+ req.doneCb(error);
2268
+ return;
2269
+ } else {
2270
+ // signal the version 1 walk code below that it should stop
2271
+ done = 1;
2272
+ }
2273
+ } else {
2274
+ req.doneCb(error);
2275
+ return;
2276
+ }
2277
+ }
2278
+
2279
+ if (this.version == Version2c || this.version == Version3) {
2280
+ for (var i = varbinds[0].length; i > 0; i--) {
2281
+ if (varbinds[0][i - 1].type == ObjectType.EndOfMibView) {
2282
+ varbinds[0].pop();
2283
+ done = 1;
2284
+ }
2285
+ }
2286
+ if (req.feedCb(varbinds[0]))
2287
+ done = 1;
2288
+ if (!done)
2289
+ oid = varbinds[0][varbinds[0].length - 1].oid;
2290
+ } else {
2291
+ if (!done) {
2292
+ if (req.feedCb(varbinds)) {
2293
+ done = 1;
2294
+ } else {
2295
+ oid = varbinds[0].oid;
2296
+ }
2297
+ }
2298
+ }
2299
+
2300
+ if (done)
2301
+ req.doneCb(null);
2302
+ else
2303
+ this.walk(oid, req.maxRepetitions, req.feedCb, req.doneCb,
2304
+ req.baseOid);
2305
+}
2306
1241
- this.subtree (oid, maxRepetitions, tableFeedCb.bind (me, req),
1242
- tableResponseCb.bind (me, req));
2307
+Session.prototype.walk = function () {
2308
+ var me = this;
2309
+ var oid = arguments[0];
2310
+ var maxRepetitions, feedCb, doneCb, baseOid;
2311
+
2312
+ if (arguments.length < 4) {
2313
+ maxRepetitions = 20;
2314
+ feedCb = arguments[1];
2315
+ doneCb = arguments[2];
2316
+ } else {
2317
+ maxRepetitions = arguments[1];
2318
+ feedCb = arguments[2];
2319
+ doneCb = arguments[3];
2320
+ }
2321
+
2322
+ var req = {
2323
+ maxRepetitions: maxRepetitions,
2324
+ feedCb: feedCb,
2325
+ doneCb: doneCb
2326
+ };
2327
+
2328
+ if (this.version == Version2c || this.version == Version3)
2329
+ this.getBulk([oid], 0, maxRepetitions,
2330
+ walkCb.bind(me, req));
2331
+ else
2332
+ this.getNext([oid], walkCb.bind(me, req));
2333
+
2334
+ return this;
2335
+};
2336
1244
- return this;
2337
+Session.prototype.sendV3Req = function (pdu, feedCb, responseCb, options, port) {
2338
+ var message = Message.createRequestV3(this.user, this.msgSecurityParameters, pdu);
2339
+ var reqOptions = options || {};
2340
+ var req = new Req(this, message, feedCb, responseCb, reqOptions);
2341
+ req.port = port;
2342
+ this.send(req);
2343
};
2344
1247
-Session.prototype.trap = function () {
1248
- var req = {};
1249
-
1250
- try {
1251
- var typeOrOid = arguments[0];
1252
- var varbinds, options = {}, responseCb;
1253
-
1254
- /**
1255
- ** Support the following signatures:
1256
- **
1257
- ** typeOrOid, varbinds, options, callback
1258
- ** typeOrOid, varbinds, agentAddr, callback
1259
- ** typeOrOid, varbinds, callback
1260
- ** typeOrOid, agentAddr, callback
1261
- ** typeOrOid, options, callback
1262
- ** typeOrOid, callback
1263
- **/
1264
- if (arguments.length >= 4) {
1265
- varbinds = arguments[1];
1266
- if (typeof arguments[2] == "string") {
1267
- options.agentAddr = arguments[2];
1268
- } else if (arguments[2].constructor != Array) {
1269
- options = arguments[2];
1270
- }
1271
- responseCb = arguments[3];
1272
- } else if (arguments.length >= 3) {
1273
- if (typeof arguments[1] == "string") {
1274
- varbinds = [];
1275
- options.agentAddr = arguments[1];
1276
- } else if (arguments[1].constructor != Array) {
1277
- varbinds = [];
1278
- options = arguments[1];
1279
- } else {
1280
- varbinds = arguments[1];
1281
- agentAddr = null;
1282
- }
1283
- responseCb = arguments[2];
1284
- } else {
1285
- varbinds = [];
1286
- responseCb = arguments[1];
1287
- }
1288
-
1289
- var pdu, pduVarbinds = [];
1290
-
1291
- for (var i = 0; i < varbinds.length; i++) {
1292
- var varbind = {
1293
- oid: varbinds[i].oid,
1294
- type: varbinds[i].type,
1295
- value: varbinds[i].value
1296
- };
1297
- pduVarbinds.push (varbind);
1298
- }
1299
-
1300
- var id = _generateId (this.idBitsSize);
1301
-
1302
- if (this.version == Version2c) {
1303
- if (typeof typeOrOid != "string")
1304
- typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
1305
-
1306
- pduVarbinds.unshift (
1307
- {
1308
- oid: "1.3.6.1.2.1.1.3.0",
1309
- type: ObjectType.TimeTicks,
1310
- value: options.upTime || Math.floor (process.uptime () * 100)
1311
- },
1312
- {
1313
- oid: "1.3.6.1.6.3.1.1.4.1.0",
1314
- type: ObjectType.OID,
1315
- value: typeOrOid
1316
- }
1317
- );
1318
-
1319
- pdu = new TrapV2Pdu (id, pduVarbinds, options);
1320
- } else {
1321
- pdu = new TrapPdu (typeOrOid, pduVarbinds, options);
1322
- }
1323
-
1324
- var message = new RequestMessage (this.version, this.community, pdu);
1325
-
1326
- req = {
1327
- id: id,
1328
- message: message,
1329
- responseCb: responseCb,
1330
- port: this.trapPort
1331
- };
1332
-
1333
- this.send (req, true);
1334
- } catch (error) {
1335
- if (req.responseCb)
1336
- req.responseCb (error);
1337
- }
1338
-
1339
- return this;
2345
+var Engine = function (engineID, engineBoots, engineTime) {
2346
+ if (engineID) {
2347
+ this.engineID = Buffer.from(engineID, 'hex');
2348
+ } else {
2349
+ this.generateEngineID();
2350
+ }
2351
+ this.engineBoots = 0;
2352
+ this.engineTime = 10;
2353
};
2354
1342
-Session.prototype.unregisterRequest = function (id) {
1343
- var req = this.reqs[id];
1344
- if (req) {
1345
- delete this.reqs[id];
1346
- clearTimeout (req.timer);
1347
- delete req.timer;
1348
- this.reqCount--;
1349
- if (this.reqCount <= 0)
1350
- this.dgram.unref();
1351
- return req;
1352
- } else {
1353
- return null;
1354
- }
1355
-};
1356
-
1357
-function walkCb (req, error, varbinds) {
1358
- var done = 0;
1359
- var oid;
1360
-
1361
- if (error) {
1362
- if (error instanceof RequestFailedError) {
1363
- if (error.status != ErrorStatus.NoSuchName) {
1364
- req.doneCb (error);
1365
- return;
1366
- } else {
1367
- // signal the version 1 walk code below that it should stop
1368
- done = 1;
1369
- }
1370
- } else {
1371
- req.doneCb (error);
1372
- return;
1373
- }
1374
- }
1375
-
1376
- if (this.version == Version2c) {
1377
- for (var i = varbinds[0].length; i > 0; i--) {
1378
- if (varbinds[0][i - 1].type == ObjectType.EndOfMibView) {
1379
- varbinds[0].pop ();
1380
- done = 1;
1381
- }
1382
- }
1383
- if (req.feedCb (varbinds[0]))
1384
- done = 1;
1385
- if (! done)
1386
- oid = varbinds[0][varbinds[0].length - 1].oid;
1387
- } else {
1388
- if (! done) {
1389
- if (req.feedCb (varbinds)) {
1390
- done = 1;
1391
- } else {
1392
- oid = varbinds[0].oid;
1393
- }
1394
- }
1395
- }
1396
-
1397
- if (done)
1398
- req.doneCb (null);
1399
- else
1400
- this.walk (oid, req.maxRepetitions, req.feedCb, req.doneCb,
1401
- req.baseOid);
2355
+Engine.prototype.generateEngineID = function () {
2356
+ // generate a 17-byte engine ID in the following format:
2357
+ // 0x80 + 0x00B983 (enterprise OID) | 0x80 (enterprise-specific format) | 12 bytes of random
2358
+ this.engineID = Buffer.alloc(17);
2359
+ this.engineID.fill('8000B98380', 'hex', 0, 5);
2360
+ this.engineID.fill(crypto.randomBytes(12), 5, 17, 'hex');
2361
+}
2362
+
2363
+var Listener = function (options, receiver) {
2364
+ this.receiver = receiver;
2365
+ this.callback = receiver.onMsg;
2366
+ this.family = options.transport || 'udp4';
2367
+ this.port = options.port || 161;
2368
+ this.disableAuthorization = options.disableAuthorization || false;
2369
+};
2370
+
2371
+Listener.prototype.startListening = function (receiver) {
2372
+ var me = this;
2373
+ this.dgram = dgram.createSocket(this.family);
2374
+ this.dgram.bind(this.port);
2375
+ this.dgram.on("message", me.callback.bind(me.receiver));
2376
+};
2377
+
2378
+Listener.prototype.send = function (message, rinfo) {
2379
+ var me = this;
2380
+
2381
+ var buffer = message.toBuffer();
2382
+
2383
+ this.dgram.send(buffer, 0, buffer.length, rinfo.port, rinfo.address,
2384
+ function (error, bytes) {
2385
+ if (error) {
2386
+ // me.callback (error);
2387
+ console.error("Error sending: " + error.message);
2388
+ } else {
2389
+ // debug ("Listener sent response message");
2390
+ }
2391
+ });
2392
+};
2393
+
2394
+Listener.formatCallbackData = function (pdu, rinfo) {
2395
+ if (pdu.contextEngineID) {
2396
+ pdu.contextEngineID = pdu.contextEngineID.toString('hex');
2397
+ }
2398
+ delete pdu.nonRepeaters;
2399
+ delete pdu.maxRepetitions;
2400
+ return {
2401
+ pdu: pdu,
2402
+ rinfo: rinfo
2403
+ };
2404
+};
2405
+
2406
+Listener.processIncoming = function (buffer, authorizer, callback) {
2407
+ var message = Message.createFromBuffer(buffer);
2408
+ var community;
2409
+
2410
+ // Authorization
2411
+ if (message.version == Version3) {
2412
+ message.user = authorizer.users.filter(localUser => localUser.name ==
2413
+ message.msgSecurityParameters.msgUserName)[0];
2414
+ message.disableAuthentication = authorizer.disableAuthorization;
2415
+ if (!message.user) {
2416
+ if (message.msgSecurityParameters.msgUserName != "" && !authorizer.disableAuthorization) {
2417
+ callback(new RequestFailedError("Local user not found for message with user " +
2418
+ message.msgSecurityParameters.msgUserName));
2419
+ return;
2420
+ } else if (message.hasAuthentication()) {
2421
+ callback(new RequestFailedError("Local user not found and message requires authentication with user " +
2422
+ message.msgSecurityParameters.msgUserName));
2423
+ return;
2424
+ } else {
2425
+ message.user = {
2426
+ name: "",
2427
+ level: SecurityLevel.noAuthNoPriv
2428
+ };
2429
+ }
2430
+ }
2431
+ if (!message.processIncomingSecurity(message.user, callback)) {
2432
+ return;
2433
+ }
2434
+ } else {
2435
+ community = authorizer.communities.filter(localCommunity => localCommunity == message.community)[0];
2436
+ if (!community && !authorizer.disableAuthorization) {
2437
+ callback(new RequestFailedError("Local community not found for message with community " + message.community));
2438
+ return;
2439
+ }
2440
+ }
2441
+
2442
+ return message;
2443
+};
2444
+
2445
+var Authorizer = function () {
2446
+ this.communities = [];
2447
+ this.users = [];
2448
+}
2449
+
2450
+Authorizer.prototype.addCommunity = function (community) {
2451
+ if (this.getCommunity(community)) {
2452
+ return;
2453
+ } else {
2454
+ this.communities.push(community);
2455
+ }
2456
+};
2457
+
2458
+Authorizer.prototype.getCommunity = function (community) {
2459
+ return this.communities.filter(localCommunity => localCommunity == community)[0] || null;
2460
+};
2461
+
2462
+Authorizer.prototype.getCommunities = function () {
2463
+ return this.communities;
2464
+};
2465
+
2466
+Authorizer.prototype.deleteCommunity = function (community) {
2467
+ var index = this.communities.indexOf(community);
2468
+ if (index > -1) {
2469
+ this.communities.splice(index, 1);
2470
+ }
2471
+};
2472
+
2473
+Authorizer.prototype.addUser = function (user) {
2474
+ if (this.getUser(user.name)) {
2475
+ this.deleteUser(user.name);
2476
+ }
2477
+ this.users.push(user);
2478
+};
2479
+
2480
+Authorizer.prototype.getUser = function (userName) {
2481
+ return this.users.filter(localUser => localUser.name == userName)[0] || null;
2482
+};
2483
+
2484
+Authorizer.prototype.getUsers = function () {
2485
+ return this.users;
2486
+};
2487
+
2488
+Authorizer.prototype.deleteUser = function (userName) {
2489
+ var index = this.users.findIndex(localUser => localUser.name == userName);
2490
+ if (index > -1) {
2491
+ this.users.splice(index, 1);
2492
+ }
2493
+};
2494
+
2495
+
2496
+/*****************************************************************************
2497
+ ** Receiver class definition
2498
+ **/
2499
+
2500
+var Receiver = function (options, callback) {
2501
+ DEBUG = options.debug;
2502
+ this.listener = new Listener(options, this);
2503
+ this.authorizer = new Authorizer();
2504
+ this.engine = new Engine(options.engineID);
2505
+
2506
+ this.engineBoots = 0;
2507
+ this.engineTime = 10;
2508
+ this.disableAuthorization = false;
2509
+
2510
+ this.callback = callback;
2511
+ this.family = options.transport || 'udp4';
2512
+ this.port = options.port || 162;
2513
+ options.port = this.port;
2514
+ this.disableAuthorization = options.disableAuthorization || false;
2515
+ this.context = (options && options.context) ? options.context : "";
2516
+ this.listener = new Listener(options, this);
2517
+};
2518
+
2519
+Receiver.prototype.addCommunity = function (community) {
2520
+ this.authorizer.addCommunity(community);
2521
+};
2522
+
2523
+Receiver.prototype.getCommunity = function (community) {
2524
+ return this.authorizer.getCommunity(community);
2525
+};
2526
+
2527
+Receiver.prototype.getCommunities = function () {
2528
+ return this.authorizer.getCommunities();
2529
+};
2530
+
2531
+Receiver.prototype.deleteCommunity = function (community) {
2532
+ this.authorizer.deleteCommunities(community);
2533
+};
2534
+
2535
+Receiver.prototype.addUser = function (user) {
2536
+ this.authorizer.addUser(user);
2537
+};
2538
+
2539
+Receiver.prototype.getUser = function (userName) {
2540
+ return this.authorizer.getUser(userName);
2541
+};
2542
+
2543
+Receiver.prototype.getUsers = function () {
2544
+ return this.authorizer.getUsers();
2545
+};
2546
+
2547
+Receiver.prototype.deleteUser = function (userName) {
2548
+ this.authorizer.deleteUser(userName);
2549
+};
2550
+
2551
+Receiver.prototype.onMsg = function (buffer, rinfo) {
2552
+ var message = Listener.processIncoming(buffer, this.authorizer, this.callback);
2553
+ var reportMessage;
2554
+
2555
+ if (!message) {
2556
+ return;
2557
+ }
2558
+
2559
+ // The only GetRequest PDUs supported are those used for SNMPv3 discovery
2560
+ if (message.pdu.type == PduType.GetRequest) {
2561
+ if (message.version != Version3) {
2562
+ this.callback(new RequestInvalidError("Only SNMPv3 discovery GetRequests are supported"));
2563
+ return;
2564
+ } else if (message.hasAuthentication()) {
2565
+ this.callback(new RequestInvalidError("Only discovery (noAuthNoPriv) GetRequests are supported but this message has authentication"));
2566
+ return;
2567
+ } else if (!message.isReportable()) {
2568
+ this.callback(new RequestInvalidError("Only discovery GetRequests are supported and this message does not have the reportable flag set"));
2569
+ return;
2570
+ }
2571
+ var reportMessage = message.createReportResponseMessage(this.engine, this.context);
2572
+ this.listener.send(reportMessage, rinfo);
2573
+ return;
2574
+ }
2575
+ ;
2576
+
2577
+ // Inform/trap processing
2578
+ debug(JSON.stringify(message.pdu, null, 2));
2579
+ if (message.pdu.type == PduType.Trap || message.pdu.type == PduType.TrapV2) {
2580
+ this.callback(null, this.formatCallbackData(message.pdu, rinfo));
2581
+ } else if (message.pdu.type == PduType.InformRequest) {
2582
+ message.pdu.type = PduType.GetResponse;
2583
+ message.buffer = null;
2584
+ message.setReportable(false);
2585
+ this.listener.send(message, rinfo);
2586
+ message.pdu.type = PduType.InformRequest;
2587
+ this.callback(null, this.formatCallbackData(message.pdu, rinfo));
2588
+ } else {
2589
+ this.callback(new RequestInvalidError("Unexpected PDU type " + message.pdu.type + " (" + PduType[message.pdu.type] + ")"));
2590
+ }
2591
}
2592
1404
-Session.prototype.walk = function () {
1405
- var me = this;
1406
- var oid = arguments[0];
1407
- var maxRepetitions, feedCb, doneCb, baseOid;
2593
+Receiver.prototype.formatCallbackData = function (pdu, rinfo) {
2594
+ if (pdu.contextEngineID) {
2595
+ pdu.contextEngineID = pdu.contextEngineID.toString('hex');
2596
+ }
2597
+ delete pdu.nonRepeaters;
2598
+ delete pdu.maxRepetitions;
2599
+ return {
2600
+ pdu: pdu,
2601
+ rinfo: rinfo
2602
+ };
2603
+};
2604
+
2605
+Receiver.prototype.close = function () {
2606
+ this.listener.close();
2607
+};
2608
+
2609
+Receiver.create = function (options, callback) {
2610
+ var receiver = new Receiver(options, callback);
2611
+ receiver.listener.startListening();
2612
+ return receiver;
2613
+};
2614
+
2615
+var MibNode = function (address, parent) {
2616
+ this.address = address;
2617
+ this.oid = this.address.join('.');
2618
+ ;
2619
+ this.parent = parent;
2620
+ this.children = {};
2621
+};
2622
+
2623
+MibNode.prototype.child = function (index) {
2624
+ return this.children[index];
2625
+};
2626
+
2627
+MibNode.prototype.listChildren = function (lowest) {
2628
+ var sorted = [];
2629
+
2630
+ lowest = lowest || 0;
2631
+
2632
+ this.children.forEach(function (c, i) {
2633
+ if (i >= lowest)
2634
+ sorted.push(i);
2635
+ });
2636
+
2637
+ sorted.sort(function (a, b) {
2638
+ return (a - b);
2639
+ });
2640
+
2641
+ return sorted;
2642
+};
2643
+
2644
+MibNode.prototype.isDescendant = function (address) {
2645
+ return MibNode.oidIsDescended(this.address, address);
2646
+};
2647
+
2648
+MibNode.prototype.isAncestor = function (address) {
2649
+ return MibNode.oidIsDescended(address, this.address);
2650
+};
2651
+
2652
+MibNode.prototype.getAncestorProvider = function () {
2653
+ if (this.provider) {
2654
+ return this;
2655
+ } else if (!this.parent) {
2656
+ return null;
2657
+ } else {
2658
+ return this.parent.getAncestorProvider();
2659
+ }
2660
+};
2661
+
2662
+MibNode.prototype.getInstanceNodeForTableRow = function () {
2663
+ var childCount = Object.keys(this.children).length;
2664
+ if (childCount == 0) {
2665
+ if (this.value) {
2666
+ return this;
2667
+ } else {
2668
+ return null;
2669
+ }
2670
+ } else if (childCount == 1) {
2671
+ return this.children[0].getInstanceNodeForTableRow();
2672
+ } else if (childCount > 1) {
2673
+ return null;
2674
+ }
2675
+};
2676
+
2677
+MibNode.prototype.getInstanceNodeForTableRowIndex = function (index) {
2678
+ var childCount = Object.keys(this.children).length;
2679
+ if (childCount == 0) {
2680
+ if (this.value) {
2681
+ return this;
2682
+ } else {
2683
+ // not found
2684
+ return null;
2685
+ }
2686
+ } else {
2687
+ if (index.length == 0) {
2688
+ return this.getInstanceNodeForTableRow();
2689
+ } else {
2690
+ var nextChildIndexPart = index[0];
2691
+ if (!nextChildIndexPart) {
2692
+ return null;
2693
+ }
2694
+ remainingIndex = index.slice(1);
2695
+ return this.children[nextChildIndexPart].getInstanceNodeForTableRowIndex(remainingIndex);
2696
+ }
2697
+ }
2698
+};
2699
+
2700
+MibNode.prototype.getNextInstanceNode = function () {
2701
+
2702
+ node = this;
2703
+ if (this.value) {
2704
+ // Need upwards traversal first
2705
+ node = this;
2706
+ while (node) {
2707
+ siblingIndex = node.address.slice(-1)[0];
2708
+ node = node.parent;
2709
+ if (!node) {
2710
+ // end of MIB
2711
+ return null;
2712
+ } else {
2713
+ childrenAddresses = Object.keys(node.children).sort((a, b) => a - b);
2714
+ siblingPosition = childrenAddresses.indexOf(siblingIndex.toString());
2715
+ if (siblingPosition + 1 < childrenAddresses.length) {
2716
+ node = node.children[childrenAddresses[siblingPosition + 1]];
2717
+ break;
2718
+ }
2719
+ }
2720
+ }
2721
+ }
2722
+ // Descent
2723
+ while (node) {
2724
+ if (node.value) {
2725
+ return node;
2726
+ }
2727
+ childrenAddresses = Object.keys(node.children).sort((a, b) => a - b);
2728
+ node = node.children[childrenAddresses[0]];
2729
+ if (!node) {
2730
+ // unexpected
2731
+ return null;
2732
+ }
2733
+ }
2734
+};
2735
+
2736
+MibNode.prototype.delete = function () {
2737
+ if (Object.keys(this.children) > 0) {
2738
+ throw new Error("Cannot delete non-leaf MIB node");
2739
+ }
2740
+ addressLastPart = this.address.slice(-1)[0];
2741
+ delete this.parent.children[addressLastPart];
2742
+ this.parent = null;
2743
+};
2744
+
2745
+MibNode.prototype.pruneUpwards = function () {
2746
+ if (!this.parent) {
2747
+ return
2748
+ }
2749
+ if (Object.keys(this.children).length == 0) {
2750
+ var lastAddressPart = this.address.splice(-1)[0].toString();
2751
+ delete this.parent.children[lastAddressPart];
2752
+ this.parent.pruneUpwards();
2753
+ this.parent = null;
2754
+ }
2755
+}
2756
+
2757
+MibNode.prototype.dump = function (options) {
2758
+ var valueString;
2759
+ if ((!options.leavesOnly || options.showProviders) && this.provider) {
2760
+ console.log(this.oid + " [" + MibProviderType[this.provider.type] + ": " + this.provider.name + "]");
2761
+ } else if ((!options.leavesOnly) || Object.keys(this.children).length == 0) {
2762
+ if (this.value) {
2763
+ valueString = " = ";
2764
+ valueString += options.showTypes ? ObjectType[this.valueType] + ": " : "";
2765
+ valueString += options.showValues ? this.value : "";
2766
+ } else {
2767
+ valueString = "";
2768
+ }
2769
+ console.log(this.oid + valueString);
2770
+ }
2771
+ for (node of Object.keys(this.children).sort((a, b) => a - b)) {
2772
+ this.children[node].dump(options);
2773
+ }
2774
+};
2775
+
2776
+MibNode.oidIsDescended = function (oid, ancestor) {
2777
+ var ancestorAddress = Mib.convertOidToAddress(ancestor);
2778
+ var address = Mib.convertOidToAddress(oid);
2779
+ var isAncestor = true;
2780
+
2781
+ if (address.length <= ancestorAddress.length) {
2782
+ return false;
2783
+ }
2784
1409
- if (arguments.length < 4) {
1410
- maxRepetitions = 20;
1411
- feedCb = arguments[1];
1412
- doneCb = arguments[2];
1413
- } else {
1414
- maxRepetitions = arguments[1];
1415
- feedCb = arguments[2];
1416
- doneCb = arguments[3];
1417
- }
2785
+ ancestorAddress.forEach(function (o, i) {
2786
+ if (address[i] !== ancestorAddress[i]) {
2787
+ isAncestor = false;
2788
+ }
2789
+ });
2790
1419
- var req = {
1420
- maxRepetitions: maxRepetitions,
1421
- feedCb: feedCb,
1422
- doneCb: doneCb
1423
- };
2791
+ return isAncestor;
2792
+};
2793
+
2794
+var Mib = function () {
2795
+ this.root = new MibNode([], null);
2796
+ this.providers = {};
2797
+ this.providerNodes = {};
2798
+};
2799
+
2800
+Mib.prototype.addNodesForOid = function (oidString) {
2801
+ var address = Mib.convertOidToAddress(oidString);
2802
+ return this.addNodesForAddress(address);
2803
+};
2804
+
2805
+Mib.prototype.addNodesForAddress = function (address) {
2806
+ var address;
2807
+ var node;
2808
+ var i;
2809
+
2810
+ node = this.root;
2811
+
2812
+ for (i = 0; i < address.length; i++) {
2813
+ if (!node.children.hasOwnProperty(address[i])) {
2814
+ node.children[address[i]] = new MibNode(address.slice(0, i + 1), node);
2815
+ }
2816
+ node = node.children[address[i]];
2817
+ }
2818
+
2819
+ return node;
2820
+};
2821
+
2822
+Mib.prototype.lookup = function (oid) {
2823
+ var address;
2824
+ var i;
2825
+ var node;
2826
+
2827
+ address = Mib.convertOidToAddress(oid);
2828
+ node = this.root;
2829
+ for (i = 0; i < address.length; i++) {
2830
+ if (!node.children.hasOwnProperty(address[i])) {
2831
+ return null
2832
+ }
2833
+ node = node.children[address[i]];
2834
+ }
2835
+
2836
+ return node;
2837
+};
2838
+
2839
+Mib.prototype.getProviderNodeForInstance = function (instanceNode) {
2840
+ if (instanceNode.provider) {
2841
+ throw new ReferenceError("Instance node has provider which should never happen");
2842
+ }
2843
+ return instanceNode.getAncestorProvider();
2844
+};
2845
+
2846
+Mib.prototype.addProviderToNode = function (provider) {
2847
+ var node = this.addNodesForOid(provider.oid);
2848
+
2849
+ node.provider = provider;
2850
+ if (provider.type == MibProviderType.Table) {
2851
+ if (!provider.index) {
2852
+ provider.index = [1];
2853
+ }
2854
+ }
2855
+ this.providerNodes[provider.name] = node;
2856
+ return node;
2857
+};
2858
+
2859
+Mib.prototype.registerProvider = function (provider) {
2860
+ this.providers[provider.name] = provider;
2861
+};
2862
+
2863
+Mib.prototype.unregisterProvider = function (name) {
2864
+ var providerNode = this.providerNodes[name];
2865
+ if (providerNode) {
2866
+ providerNodeParent = providerNode.parent;
2867
+ providerNode.delete();
2868
+ providerNodeParent.pruneUpwards();
2869
+ delete this.providerNodes[name];
2870
+ }
2871
+ delete this.providers[name];
2872
+};
2873
+
2874
+Mib.prototype.getProvider = function (name) {
2875
+ return this.providers[name];
2876
+};
2877
+
2878
+Mib.prototype.getProviders = function () {
2879
+ return this.providers;
2880
+};
2881
+
2882
+Mib.prototype.getScalarValue = function (scalarName) {
2883
+ var providerNode = this.providerNodes[scalarName];
2884
+ if (!providerNode || !providerNode.provider || providerNode.provider.type != MibProviderType.Scalar) {
2885
+ throw new ReferenceError("Failed to get node for registered MIB provider " + scalarName);
2886
+ }
2887
+ var instanceAddress = providerNode.address.concat([0]);
2888
+ if (!this.lookup(instanceAddress)) {
2889
+ throw new Error("Failed created instance node for registered MIB provider " + scalarName);
2890
+ }
2891
+ var instanceNode = this.lookup(instanceAddress);
2892
+ return instanceNode.value;
2893
+};
2894
+
2895
+Mib.prototype.setScalarValue = function (scalarName, newValue) {
2896
+ var providerNode;
2897
+ var instanceNode;
2898
+
2899
+ if (!this.providers[scalarName]) {
2900
+ throw new ReferenceError("Provider " + scalarName + " not registered with this MIB");
2901
+ }
2902
+
2903
+ providerNode = this.providerNodes[scalarName];
2904
+ if (!providerNode) {
2905
+ providerNode = this.addProviderToNode(this.providers[scalarName]);
2906
+ }
2907
+ if (!providerNode || !providerNode.provider || providerNode.provider.type != MibProviderType.Scalar) {
2908
+ throw new ReferenceError("Could not find MIB node for registered provider " + scalarName);
2909
+ }
2910
+ var instanceAddress = providerNode.address.concat([0]);
2911
+ instanceNode = this.lookup(instanceAddress);
2912
+ if (!instanceNode) {
2913
+ this.addNodesForAddress(instanceAddress);
2914
+ instanceNode = this.lookup(instanceAddress);
2915
+ instanceNode.valueType = providerNode.provider.scalarType;
2916
+ }
2917
+ instanceNode.value = newValue;
2918
+};
2919
+
2920
+Mib.prototype.getProviderNodeForTable = function (table) {
2921
+ var providerNode;
2922
+ var provider;
2923
+
2924
+ providerNode = this.providerNodes[table];
2925
+ if (!providerNode) {
2926
+ throw new ReferenceError("No MIB provider registered for " + table);
2927
+ }
2928
+ provider = providerNode.provider;
2929
+ if (!providerNode) {
2930
+ throw new ReferenceError("No MIB provider definition for registered provider " + table);
2931
+ }
2932
+ if (provider.type != MibProviderType.Table) {
2933
+ throw new TypeError("Registered MIB provider " + table +
2934
+ " is not of the correct type (is type " + MibProviderType[provider.type] + ")");
2935
+ }
2936
+ return providerNode;
2937
+};
2938
+
2939
+Mib.prototype.addTableRow = function (table, row) {
2940
+ var providerNode;
2941
+ var provider;
2942
+ var instance = [];
2943
+ var instanceAddress;
2944
+ var instanceNode;
2945
+
2946
+ if (this.providers[table] && !this.providerNodes[table]) {
2947
+ this.addProviderToNode(this.providers[table]);
2948
+ }
2949
+ providerNode = this.getProviderNodeForTable(table);
2950
+ provider = providerNode.provider;
2951
+ for (var indexPart of provider.index) {
2952
+ columnPosition = provider.columns.findIndex(column => column.number == indexPart);
2953
+ instance.push(row[columnPosition]);
2954
+ }
2955
+ for (var i = 0; i < providerNode.provider.columns.length; i++) {
2956
+ var column = providerNode.provider.columns[i];
2957
+ instanceAddress = providerNode.address.concat(column.number).concat(instance);
2958
+ this.addNodesForAddress(instanceAddress);
2959
+ instanceNode = this.lookup(instanceAddress);
2960
+ instanceNode.valueType = column.type;
2961
+ instanceNode.value = row[i];
2962
+ }
2963
+};
2964
+
2965
+Mib.prototype.getTableColumnDefinitions = function (table) {
2966
+ var providerNode;
2967
+ var provider;
2968
+
2969
+ providerNode = this.getProviderNodeForTable(table);
2970
+ provider = providerNode.provider;
2971
+ return provider.columns;
2972
+};
2973
+
2974
+Mib.prototype.getTableColumnCells = function (table, columnNumber) {
2975
+ providerNode = this.getProviderNodeForTable(table);
2976
+ columnNode = providerNode.children[columnNumber];
2977
+ column = []
2978
+ for (var row of Object.keys(columnNode.children)) {
2979
+ instanceNode = columnNode.children[row].getInstanceNodeForTableRow();
2980
+ column.push(instanceNode.value);
2981
+ }
2982
+ return column;
2983
+};
2984
+
2985
+Mib.prototype.getTableRowCells = function (table, rowIndex) {
2986
+ var providerNode;
2987
+ var columnNode;
2988
+ var instanceNode;
2989
+ var row = [];
2990
+
2991
+ providerNode = this.getProviderNodeForTable(table);
2992
+ for (var columnNumber of Object.keys(providerNode.children)) {
2993
+ columnNode = providerNode.children[columnNumber];
2994
+ instanceNode = columnNode.getInstanceNodeForTableRowIndex(rowIndex);
2995
+ row.push(instanceNode.value);
2996
+ }
2997
+ return row;
2998
+};
2999
+
3000
+Mib.prototype.getTableCells = function (table, byRows) {
3001
+ var providerNode;
3002
+ var columnNode;
3003
+ var data = [];
3004
+
3005
+ providerNode = this.getProviderNodeForTable(table);
3006
+ for (var columnNumber of Object.keys(providerNode.children)) {
3007
+ columnNode = providerNode.children[columnNumber];
3008
+ column = [];
3009
+ data.push(column);
3010
+ for (var row of Object.keys(columnNode.children)) {
3011
+ instanceNode = columnNode.children[row].getInstanceNodeForTableRow();
3012
+ column.push(instanceNode.value);
3013
+ }
3014
+ }
3015
+
3016
+ if (byRows) {
3017
+ return Object.keys(data[0]).map(function (c) {
3018
+ return data.map(function (r) {
3019
+ return r[c];
3020
+ });
3021
+ });
3022
+ } else {
3023
+ return data;
3024
+ }
3025
+
3026
+};
3027
+
3028
+Mib.prototype.getTableSingleCell = function (table, columnNumber, rowIndex) {
3029
+ var providerNode;
3030
+ var columnNode;
3031
+ var instanceNode;
3032
+
3033
+ providerNode = this.getProviderNodeForTable(table);
3034
+ columnNode = providerNode.children[columnNumber];
3035
+ instanceNode = columnNode.getInstanceNodeForTableRowIndex(rowIndex);
3036
+ return instanceNode.value;
3037
+};
3038
+
3039
+Mib.prototype.setTableSingleCell = function (table, columnNumber, rowIndex, value) {
3040
+ var providerNode;
3041
+ var columnNode;
3042
+ var instanceNode;
3043
+
3044
+ providerNode = this.getProviderNodeForTable(table);
3045
+ columnNode = providerNode.children[columnNumber];
3046
+ instanceNode = columnNode.getInstanceNodeForTableRowIndex(rowIndex);
3047
+ instanceNode.value = value;
3048
+};
3049
+
3050
+Mib.prototype.deleteTableRow = function (table, rowIndex) {
3051
+ var providerNode;
3052
+ var columnNode;
3053
+ var instanceNode;
3054
+ var row = [];
3055
+
3056
+ providerNode = this.getProviderNodeForTable(table);
3057
+ for (var columnNumber of Object.keys(providerNode.children)) {
3058
+ columnNode = providerNode.children[columnNumber];
3059
+ instanceNode = columnNode.getInstanceNodeForTableRowIndex(rowIndex);
3060
+ if (instanceNode) {
3061
+ instanceParentNode = instanceNode.parent;
3062
+ instanceNode.delete();
3063
+ instanceParentNode.pruneUpwards();
3064
+ } else {
3065
+ throw new ReferenceError("Cannot find row for index " + rowIndex + " at registered provider " + table);
3066
+ }
3067
+ }
3068
+ return row;
3069
+};
3070
+
3071
+Mib.prototype.dump = function (options) {
3072
+ if (!options) {
3073
+ options = {};
3074
+ }
3075
+ var completedOptions = {
3076
+ leavesOnly: options.leavesOnly || true,
3077
+ showProviders: options.leavesOnly || true,
3078
+ showValues: options.leavesOnly || true,
3079
+ showTypes: options.leavesOnly || true
3080
+ };
3081
+ this.root.dump(completedOptions);
3082
+};
3083
+
3084
+Mib.convertOidToAddress = function (oid) {
3085
+ var address;
3086
+ var oidArray;
3087
+ var i;
3088
+
3089
+ if (typeof (oid) === 'object' && util.isArray(oid)) {
3090
+ address = oid;
3091
+ } else if (typeof (oid) === 'string') {
3092
+ address = oid.split('.');
3093
+ } else {
3094
+ throw new TypeError('oid (string or array) is required');
3095
+ }
3096
+
3097
+ if (address.length < 3)
3098
+ throw new RangeError('object identifier is too short');
3099
+
3100
+ oidArray = [];
3101
+ for (i = 0; i < address.length; i++) {
3102
+ var n;
3103
+
3104
+ if (address[i] === '')
3105
+ continue;
3106
+
3107
+ if (address[i] === true || address[i] === false) {
3108
+ throw new TypeError('object identifier component ' +
3109
+ address[i] + ' is malformed');
3110
+ }
3111
+
3112
+ n = Number(address[i]);
3113
+
3114
+ if (isNaN(n)) {
3115
+ throw new TypeError('object identifier component ' +
3116
+ address[i] + ' is malformed');
3117
+ }
3118
+ if (n % 1 !== 0) {
3119
+ throw new TypeError('object identifier component ' +
3120
+ address[i] + ' is not an integer');
3121
+ }
3122
+ if (i === 0 && n > 2) {
3123
+ throw new RangeError('object identifier does not ' +
3124
+ 'begin with 0, 1, or 2');
3125
+ }
3126
+ if (i === 1 && n > 39) {
3127
+ throw new RangeError('object identifier second ' +
3128
+ 'component ' + n + ' exceeds encoding limit of 39');
3129
+ }
3130
+ if (n < 0) {
3131
+ throw new RangeError('object identifier component ' +
3132
+ address[i] + ' is negative');
3133
+ }
3134
+ if (n > MAX_INT32) {
3135
+ throw new RangeError('object identifier component ' +
3136
+ address[i] + ' is too large');
3137
+ }
3138
+ oidArray.push(n);
3139
+ }
3140
+
3141
+ return oidArray;
3142
+
3143
+};
3144
+
3145
+var MibRequest = function (requestDefinition) {
3146
+ this.operation = requestDefinition.operation;
3147
+ this.address = Mib.convertOidToAddress(requestDefinition.oid);
3148
+ this.oid = this.address.join('.');
3149
+ this.providerNode = requestDefinition.providerNode;
3150
+ this.instanceNode = requestDefinition.instanceNode;
3151
+};
3152
+
3153
+MibRequest.prototype.isScalar = function () {
3154
+ return this.providerNode && this.providerNode.provider &&
3155
+ this.providerNode.provider.type == MibProviderType.Scalar;
3156
+};
3157
1425
- if (this.version == Version2c)
1426
- this.getBulk ([oid], 0, maxRepetitions,
1427
- walkCb.bind (me, req));
1428
- else
1429
- this.getNext ([oid], walkCb.bind (me, req));
3158
+MibRequest.prototype.isTabular = function () {
3159
+ return this.providerNode && this.providerNode.provider &&
3160
+ this.providerNode.provider.type == MibProviderType.Table;
3161
+};
3162
+
3163
+var Agent = function (options, callback) {
3164
+ DEBUG = options.debug;
3165
+ this.listener = new Listener(options, this);
3166
+ this.engine = new Engine(options.engineID);
3167
+ this.authorizer = new Authorizer();
3168
+ this.mib = new Mib();
3169
+ this.callback = callback || function () {
3170
+ };
3171
+ this.context = "";
3172
+};
3173
+
3174
+Agent.prototype.getMib = function () {
3175
+ return this.mib;
3176
+};
3177
+
3178
+Agent.prototype.getAuthorizer = function () {
3179
+ return this.authorizer;
3180
+};
3181
+
3182
+Agent.prototype.registerProvider = function (provider) {
3183
+ this.mib.registerProvider(provider);
3184
+};
3185
1431
- return this;
3186
+Agent.prototype.unregisterProvider = function (provider) {
3187
+ this.mib.unregisterProvider(provider);
3188
+};
3189
+
3190
+Agent.prototype.getProvider = function (provider) {
3191
+ return this.mib.getProvider(provider);
3192
+};
3193
+
3194
+Agent.prototype.getProviders = function () {
3195
+ return this.mib.getProviders();
3196
+};
3197
+
3198
+Agent.prototype.onMsg = function (buffer, rinfo) {
3199
+ var message = Listener.processIncoming(buffer, this.authorizer, this.callback);
3200
+ var reportMessage;
3201
+ var responseMessage;
3202
+
3203
+ if (!message) {
3204
+ return;
3205
+ }
3206
+
3207
+ // SNMPv3 discovery
3208
+ if (message.version == Version3 && message.pdu.type == PduType.GetRequest &&
3209
+ !message.hasAuthoritativeEngineID() && message.isReportable()) {
3210
+ reportMessage = message.createReportResponseMessage(this.engine, this.context);
3211
+ this.listener.send(reportMessage, rinfo);
3212
+ return;
3213
+ }
3214
+
3215
+ // Request processing
3216
+ debug(JSON.stringify(message.pdu, null, 2));
3217
+ if (message.pdu.type == PduType.GetRequest) {
3218
+ responseMessage = this.request(message, rinfo);
3219
+ } else if (message.pdu.type == PduType.SetRequest) {
3220
+ responseMessage = this.request(message, rinfo);
3221
+ } else if (message.pdu.type == PduType.GetNextRequest) {
3222
+ responseMessage = this.getNextRequest(message, rinfo);
3223
+ } else if (message.pdu.type == PduType.GetBulkRequest) {
3224
+ responseMessage = this.getBulkRequest(message, rinfo);
3225
+ } else {
3226
+ this.callback(new RequestInvalidError("Unexpected PDU type " +
3227
+ message.pdu.type + " (" + PduType[message.pdu.type] + ")"));
3228
+ }
3229
+
3230
+};
3231
+
3232
+Agent.prototype.request = function (requestMessage, rinfo) {
3233
+ var me = this;
3234
+ var varbindsCompleted = 0;
3235
+ var requestPdu = requestMessage.pdu;
3236
+ var varbindsLength = requestPdu.varbinds.length;
3237
+ var responsePdu = requestPdu.getResponsePduForRequest();
3238
+
3239
+ for (var i = 0; i < requestPdu.varbinds.length; i++) {
3240
+ var requestVarbind = requestPdu.varbinds[i];
3241
+ var instanceNode = this.mib.lookup(requestVarbind.oid);
3242
+ var providerNode;
3243
+ var mibRequest;
3244
+ var handler;
3245
+ var responseVarbindType;
3246
+
3247
+ if (!instanceNode) {
3248
+ mibRequest = new MibRequest({
3249
+ operation: requestPdu.type,
3250
+ oid: requestVarbind.oid
3251
+ });
3252
+ handler = function getNsoHandler(mibRequestForNso) {
3253
+ mibRequestForNso.done({
3254
+ errorStatus: ErrorStatus.NoSuchName,
3255
+ errorIndex: i
3256
+ });
3257
+ };
3258
+ } else {
3259
+ providerNode = this.mib.getProviderNodeForInstance(instanceNode);
3260
+ mibRequest = new MibRequest({
3261
+ operation: requestPdu.type,
3262
+ providerNode: providerNode,
3263
+ instanceNode: instanceNode,
3264
+ oid: requestVarbind.oid
3265
+ });
3266
+ handler = providerNode.provider.handler;
3267
+ }
3268
+
3269
+ mibRequest.done = function (error) {
3270
+ if (error) {
3271
+ responsePdu.errorStatus = error.errorStatus;
3272
+ responsePdu.errorIndex = error.errorIndex;
3273
+ responseVarbind = {
3274
+ oid: mibRequest.oid,
3275
+ type: ObjectType.Null,
3276
+ value: null
3277
+ };
3278
+ } else {
3279
+ if (requestPdu.type == PduType.SetRequest) {
3280
+ mibRequest.instanceNode.value = requestVarbind.value;
3281
+ }
3282
+ if (requestPdu.type == PduType.GetNextRequest && requestVarbind.type == ObjectType.EndOfMibView) {
3283
+ responseVarbindType = ObjectType.EndOfMibView;
3284
+ } else {
3285
+ responseVarbindType = mibRequest.instanceNode.valueType;
3286
+ }
3287
+ responseVarbind = {
3288
+ oid: mibRequest.oid,
3289
+ type: responseVarbindType,
3290
+ value: mibRequest.instanceNode.value
3291
+ };
3292
+ }
3293
+ me.setSingleVarbind(responsePdu, i, responseVarbind);
3294
+ if (++varbindsCompleted == varbindsLength) {
3295
+ me.sendResponse.call(me, rinfo, requestMessage, responsePdu);
3296
+ }
3297
+ };
3298
+ if (handler) {
3299
+ handler(mibRequest);
3300
+ } else {
3301
+ mibRequest.done();
3302
+ }
3303
+ }
3304
+ ;
3305
+};
3306
+
3307
+Agent.prototype.addGetNextVarbind = function (targetVarbinds, startOid) {
3308
+ var startNode = this.mib.lookup(startOid);
3309
+ var getNextNode;
3310
+
3311
+ if (!startNode) {
3312
+ // Off-tree start specified
3313
+ targetVarbinds.push({
3314
+ oid: requestVarbind.oid,
3315
+ type: ObjectType.Null,
3316
+ value: null
3317
+ });
3318
+ } else {
3319
+ getNextNode = startNode.getNextInstanceNode();
3320
+ if (!getNextNode) {
3321
+ // End of MIB
3322
+ targetVarbinds.push({
3323
+ oid: requestVarbind.oid,
3324
+ type: ObjectType.EndOfMibView,
3325
+ value: null
3326
+ });
3327
+ } else {
3328
+ // Normal response
3329
+ targetVarbinds.push({
3330
+ oid: getNextNode.oid,
3331
+ type: getNextNode.valueType,
3332
+ value: getNextNode.value
3333
+ });
3334
+ }
3335
+ }
3336
+ return getNextNode;
3337
+};
3338
+
3339
+Agent.prototype.getNextRequest = function (requestMessage, rinfo) {
3340
+ var requestPdu = requestMessage.pdu;
3341
+ var varbindsLength = requestPdu.varbinds.length;
3342
+ var getNextVarbinds = [];
3343
+
3344
+ for (var i = 0; i < varbindsLength; i++) {
3345
+ this.addGetNextVarbind(getNextVarbinds, requestPdu.varbinds[i].oid);
3346
+ }
3347
+
3348
+ requestMessage.pdu.varbinds = getNextVarbinds;
3349
+ this.request(requestMessage, rinfo);
3350
+};
3351
+
3352
+Agent.prototype.getBulkRequest = function (requestMessage, rinfo) {
3353
+ var requestPdu = requestMessage.pdu;
3354
+ var requestVarbinds = requestPdu.varbinds;
3355
+ var getBulkVarbinds = [];
3356
+ var startOid = [];
3357
+ var getNextNode;
3358
+
3359
+ for (var n = 0; n < requestPdu.nonRepeaters; n++) {
3360
+ this.addGetNextVarbind(getBulkVarbinds, requestVarbinds[n].oid);
3361
+ }
3362
+
3363
+ for (var v = requestPdu.nonRepeaters; v < requestVarbinds.length; v++) {
3364
+ startOid.push(requestVarbinds[v].oid);
3365
+ }
3366
+
3367
+ for (var r = 0; r < requestPdu.maxRepetitions; r++) {
3368
+ for (var v = requestPdu.nonRepeaters; v < requestVarbinds.length; v++) {
3369
+ getNextNode = this.addGetNextVarbind(getBulkVarbinds, startOid[v - requestPdu.nonRepeaters]);
3370
+ if (getNextNode) {
3371
+ startOid[v - requestPdu.nonRepeaters] = getNextNode.oid;
3372
+ }
3373
+ }
3374
+ }
3375
+
3376
+ requestMessage.pdu.varbinds = getBulkVarbinds;
3377
+ this.request(requestMessage, rinfo);
3378
+};
3379
+
3380
+Agent.prototype.setSingleVarbind = function (responsePdu, index, responseVarbind) {
3381
+ responsePdu.varbinds[index] = responseVarbind;
3382
+};
3383
+
3384
+Agent.prototype.sendResponse = function (rinfo, requestMessage, responsePdu) {
3385
+ var responseMessage = requestMessage.createResponseForRequest(responsePdu);
3386
+ this.listener.send(responseMessage, rinfo);
3387
+ this.callback(null, Listener.formatCallbackData(responseMessage.pdu, rinfo));
3388
+};
3389
+
3390
+Agent.create = function (options, callback) {
3391
+ var agent = new Agent(options, callback);
3392
+ agent.listener.startListening();
3393
+ return agent;
3394
};
3395
3396
/*****************************************************************************
@@ -1438,18 +3400,41 @@ Session.prototype.walk = function () {
3400
exports.Session = Session;
3401
3402
exports.createSession = function (target, community, options) {
1441
- return new Session (target, community, options);
3403
+ if (options.version && !(options.version == Version1 || options.version == Version2c)) {
3404
+ throw new ResponseInvalidError("SNMP community session requested but version '" + options.version + "' specified in options not valid");
3405
+ } else {
3406
+ return new Session(target, community, options);
3407
+ }
3408
};
3409
3410
+exports.createV3Session = function (target, user, options) {
3411
+ if (options.version && options.version != Version3) {
3412
+ throw new ResponseInvalidError("SNMPv3 session requested but version '" + options.version + "' specified in options");
3413
+ } else {
3414
+ options.version = Version3;
3415
+ }
3416
+ return new Session(target, user, options);
3417
+};
3418
+
3419
+exports.createReceiver = Receiver.create;
3420
+exports.createAgent = Agent.create;
3421
+
3422
exports.isVarbindError = isVarbindError;
3423
exports.varbindError = varbindError;
3424
3425
exports.Version1 = Version1;
3426
exports.Version2c = Version2c;
3427
+exports.Version3 = Version3;
3428
+exports.Version = Version;
3429
3430
exports.ErrorStatus = ErrorStatus;
3431
exports.TrapType = TrapType;
3432
exports.ObjectType = ObjectType;
3433
+exports.PduType = PduType;
3434
+exports.MibProviderType = MibProviderType;
3435
+exports.SecurityLevel = SecurityLevel;
3436
+exports.AuthProtocols = AuthProtocols;
3437
+exports.PrivProtocols = PrivProtocols;
3438
3439
exports.ResponseInvalidError = ResponseInvalidError;
3440
exports.RequestInvalidError = RequestInvalidError;
@@ -1460,6 +3445,8 @@ exports.RequestTimedOutError = RequestTimedOutError;
3445
** We've added this for testing.
3446
**/
3447
exports.ObjectParser = {
1463
- readInt: readInt,
1464
- readUint: readUint
3448
+ readInt: readInt,
3449
+ readUint: readUint
3450
};
3451
+exports.Authentication = Authentication;
3452
+exports.Encryption = Encryption;
collectors/node.d.plugin/snmp/README.md
+204
-141
@@ -1,15 +1,20 @@
1
# SNMP Data Collector
2
3
-Using this collector, Netdata can collect data from any SNMP device.
3
+Using this collector, Netdata can collect data from any SNMP device. This collector uses [net-snmp](https://github.com/markabrahams/node-net-snmp) module.
4
5
-This collector supports:
5
+It supports:
6
7
+- all SNMP versions: SNMPv1, SNMPv2c and SNMPv3
8
- any number of SNMP devices
9
- each SNMP device can be used to collect data for any number of charts
10
- each chart may have any number of dimensions
11
- each SNMP device may have a different update frequency
12
- each SNMP device will accept one or more batches to report values (you can set `max_request_size` per SNMP server, to control the size of batches).
13
14
+## Requirements
15
+
16
+- `nodejs` minimum required version 4
17
+
18
## Configuration
19
20
You will need to create the file `/etc/netdata/node.d/snmp.conf` with data like the following.
@@ -32,7 +37,9 @@ In this example:
37
"community": "public",
38
"update_every": 10,
39
"max_request_size": 50,
35
- "options": { "timeout": 10000 },
40
+ "options": {
41
+ "timeout": 10000
42
+ },
43
"charts": {
44
"snmp_switch.bandwidth_port1": {
45
"title": "Switch Bandwidth for port 1",
@@ -109,7 +116,9 @@ If you need to define many charts using incremental OIDs, you can use something
116
"hostname": "10.11.12.8",
117
"community": "public",
118
"update_every": 10,
112
- "options": { "timeout": 20000 },
119
+ "options": {
120
+ "timeout": 20000
121
+ },
122
"charts": {
123
"snmp_switch.bandwidth_port": {
124
"title": "Switch Bandwidth for port ",
@@ -117,7 +126,10 @@ If you need to define many charts using incremental OIDs, you can use something
126
"type": "area",
127
"priority": 1,
128
"family": "ports",
120
- "multiply_range": [ 1, 24 ],
129
+ "multiply_range": [
130
+ 1,
131
+ 24
132
+ ],
133
"dimensions": {
134
"in": {
135
"oid": "1.3.6.1.2.1.2.2.1.10.",
@@ -152,11 +164,55 @@ Each of the 24 new charts will have its id (1-24) appended at:
164
165
The `options` given for each server, are:
166
155
-- `timeout`, the time to wait for the SNMP device to respond. The default is 5000 ms.
156
-- `version`, the SNMP version to use. `0` is Version 1, `1` is Version 2c. The default is Version 1 (`0`).
157
-- `transport`, the default is `udp4`.
158
-- `port`, the port of the SNMP device to connect to. The default is `161`.
159
-- `retries`, the number of attempts to make to fetch the data. The default is `1`.
167
+- `port` - UDP port to send requests too. Defaults to `161`.
168
+- `retries` - number of times to re-send a request. Defaults to `1`.
169
+- `sourceAddress` - IP address from which SNMP requests should originate, there is no default for this option, the operating system will select an appropriate source address when the SNMP request is sent.
170
+- `sourcePort` - UDP port from which SNMP requests should originate, defaults to an ephemeral port selected by the operation system.
171
+- `timeout` - number of milliseconds to wait for a response before re-trying or failing. Defaults to `5000`.
172
+- `transport` - specify the transport to use, can be either `udp4` or `udp6`. Defaults to `udp4`.
173
+- `version` - either `0` (v1) or `1` (v2) or `3` (v3). Defaults to `0`.
174
+- `idBitsSize` - either `16` or `32`. Defaults to `32`. Used to reduce the size of the generated id for compatibility with some older devices.
175
+
176
+## SNMPv3
177
+
178
+To use SNMPv3:
179
+
180
+- set `version` to 3
181
+- use `user` instead of `community`
182
+
183
+User syntax:
184
+
185
+```json
186
+{
187
+ "user": {
188
+ "name": "userName",
189
+ "level": 3,
190
+ "authProtocol": "3",
191
+ "authKey": "authKey",
192
+ "privProtocol": "2",
193
+ "privKey": "privKey"
194
+ }
195
+}
196
+```
197
+
198
+Security levels:
199
+
200
+- 1 is `noAuthNoPriv`
201
+- 2 is `authNoPriv`
202
+- 3 is `authPriv`
203
+
204
+Authentication protocols:
205
+
206
+- "1" is `none`
207
+- "2" is `md5`
208
+- "3" is `sha`
209
+
210
+Privacy protocols:
211
+
212
+- "1" is `none`
213
+- "2" is `des`
214
+
215
+For additional details please see [net-snmp module readme](https://github.com/markabrahams/node-net-snmp#snmpcreatev3session-target-user-options).
216
217
## Retrieving names from snmp
218
@@ -218,145 +274,152 @@ This switch has a very slow SNMP processors. To respond, it needs about 8 second
274
"enable_autodetect": false,
275
"update_every": 5,
276
"servers": [
221
- {
222
- "hostname": "10.11.12.8",
223
- "community": "public",
224
- "update_every": 15,
225
- "options": { "timeout": 20000, "version": 1 },
226
- "charts": {
227
- "snmp_switch.power": {
228
- "title": "Switch Power Supply",
229
- "units": "watts",
230
- "type": "line",
231
- "priority": 10,
232
- "family": "power",
233
- "dimensions": {
234
- "supply": {
235
- "oid": ".1.3.6.1.2.1.105.1.3.1.1.2.1",
236
- "algorithm": "absolute",
237
- "multiplier": 1,
238
- "divisor": 1,
239
- "offset": 0
240
- },
241
- "used": {
242
- "oid": ".1.3.6.1.2.1.105.1.3.1.1.4.1",
243
- "algorithm": "absolute",
244
- "multiplier": 1,
245
- "divisor": 1,
246
- "offset": 0
247
- }
248
- }
249
- }
250
- , "snmp_switch.input": {
251
- "title": "Switch Packets Input",
252
- "units": "packets/s",
253
- "type": "area",
254
- "priority": 20,
255
- "family": "IP",
256
- "dimensions": {
257
- "receives": {
258
- "oid": ".1.3.6.1.2.1.4.3.0",
259
- "algorithm": "incremental",
260
- "multiplier": 1,
261
- "divisor": 1,
262
- "offset": 0
263
- }
264
- , "discards": {
265
- "oid": ".1.3.6.1.2.1.4.8.0",
266
- "algorithm": "incremental",
267
- "multiplier": 1,
268
- "divisor": 1,
269
- "offset": 0
270
- }
271
- }
272
- }
273
- , "snmp_switch.input_errors": {
274
- "title": "Switch Received Packets with Errors",
275
- "units": "packets/s",
276
- "type": "line",
277
- "priority": 30,
278
- "family": "IP",
279
- "dimensions": {
280
- "bad_header": {
281
- "oid": ".1.3.6.1.2.1.4.4.0",
282
- "algorithm": "incremental",
283
- "multiplier": 1,
284
- "divisor": 1,
285
- "offset": 0
286
- }
287
- , "bad_address": {
288
- "oid": ".1.3.6.1.2.1.4.5.0",
289
- "algorithm": "incremental",
290
- "multiplier": 1,
291
- "divisor": 1,
292
- "offset": 0
293
- }
294
- , "unknown_protocol": {
295
- "oid": ".1.3.6.1.2.1.4.7.0",
296
- "algorithm": "incremental",
297
- "multiplier": 1,
298
- "divisor": 1,
299
- "offset": 0
300
- }
301
- }
302
- }
303
- , "snmp_switch.output": {
304
- "title": "Switch Output Packets",
305
- "units": "packets/s",
306
- "type": "line",
307
- "priority": 40,
308
- "family": "IP",
309
- "dimensions": {
310
- "requests": {
311
- "oid": ".1.3.6.1.2.1.4.10.0",
312
- "algorithm": "incremental",
313
- "multiplier": 1,
314
- "divisor": 1,
315
- "offset": 0
277
+ {
278
+ "hostname": "10.11.12.8",
279
+ "community": "public",
280
+ "update_every": 15,
281
+ "options": {
282
+ "timeout": 20000,
283
+ "version": 1
284
+ },
285
+ "charts": {
286
+ "snmp_switch.power": {
287
+ "title": "Switch Power Supply",
288
+ "units": "watts",
289
+ "type": "line",
290
+ "priority": 10,
291
+ "family": "power",
292
+ "dimensions": {
293
+ "supply": {
294
+ "oid": ".1.3.6.1.2.1.105.1.3.1.1.2.1",
295
+ "algorithm": "absolute",
296
+ "multiplier": 1,
297
+ "divisor": 1,
298
+ "offset": 0
299
+ },
300
+ "used": {
301
+ "oid": ".1.3.6.1.2.1.105.1.3.1.1.4.1",
302
+ "algorithm": "absolute",
303
+ "multiplier": 1,
304
+ "divisor": 1,
305
+ "offset": 0
306
+ }
307
}
317
- , "discards": {
318
- "oid": ".1.3.6.1.2.1.4.11.0",
319
- "algorithm": "incremental",
320
- "multiplier": -1,
321
- "divisor": 1,
322
- "offset": 0
308
+ },
309
+ "snmp_switch.input": {
310
+ "title": "Switch Packets Input",
311
+ "units": "packets/s",
312
+ "type": "area",
313
+ "priority": 20,
314
+ "family": "IP",
315
+ "dimensions": {
316
+ "receives": {
317
+ "oid": ".1.3.6.1.2.1.4.3.0",
318
+ "algorithm": "incremental",
319
+ "multiplier": 1,
320
+ "divisor": 1,
321
+ "offset": 0
322
+ },
323
+ "discards": {
324
+ "oid": ".1.3.6.1.2.1.4.8.0",
325
+ "algorithm": "incremental",
326
+ "multiplier": 1,
327
+ "divisor": 1,
328
+ "offset": 0
329
+ }
330
}
324
- , "no_route": {
325
- "oid": ".1.3.6.1.2.1.4.12.0",
326
- "algorithm": "incremental",
327
- "multiplier": -1,
328
- "divisor": 1,
329
- "offset": 0
331
+ },
332
+ "snmp_switch.input_errors": {
333
+ "title": "Switch Received Packets with Errors",
334
+ "units": "packets/s",
335
+ "type": "line",
336
+ "priority": 30,
337
+ "family": "IP",
338
+ "dimensions": {
339
+ "bad_header": {
340
+ "oid": ".1.3.6.1.2.1.4.4.0",
341
+ "algorithm": "incremental",
342
+ "multiplier": 1,
343
+ "divisor": 1,
344
+ "offset": 0
345
+ },
346
+ "bad_address": {
347
+ "oid": ".1.3.6.1.2.1.4.5.0",
348
+ "algorithm": "incremental",
349
+ "multiplier": 1,
350
+ "divisor": 1,
351
+ "offset": 0
352
+ },
353
+ "unknown_protocol": {
354
+ "oid": ".1.3.6.1.2.1.4.7.0",
355
+ "algorithm": "incremental",
356
+ "multiplier": 1,
357
+ "divisor": 1,
358
+ "offset": 0
359
+ }
360
}
331
- }
332
- }
333
- , "snmp_switch.bandwidth_port": {
334
- "title": "Switch Bandwidth for port ",
335
- "titleoid": ".1.3.6.1.2.1.31.1.1.1.18.",
336
- "units": "kilobits/s",
337
- "type": "area",
338
- "priority": 100,
339
- "family": "ports",
340
- "multiply_range": [ 1, 24 ],
341
- "dimensions": {
342
- "in": {
343
- "oid": ".1.3.6.1.2.1.2.2.1.10.",
344
- "algorithm": "incremental",
345
- "multiplier": 8,
346
- "divisor": 1024,
347
- "offset": 0
361
+ },
362
+ "snmp_switch.output": {
363
+ "title": "Switch Output Packets",
364
+ "units": "packets/s",
365
+ "type": "line",
366
+ "priority": 40,
367
+ "family": "IP",
368
+ "dimensions": {
369
+ "requests": {
370
+ "oid": ".1.3.6.1.2.1.4.10.0",
371
+ "algorithm": "incremental",
372
+ "multiplier": 1,
373
+ "divisor": 1,
374
+ "offset": 0
375
+ },
376
+ "discards": {
377
+ "oid": ".1.3.6.1.2.1.4.11.0",
378
+ "algorithm": "incremental",
379
+ "multiplier": -1,
380
+ "divisor": 1,
381
+ "offset": 0
382
+ },
383
+ "no_route": {
384
+ "oid": ".1.3.6.1.2.1.4.12.0",
385
+ "algorithm": "incremental",
386
+ "multiplier": -1,
387
+ "divisor": 1,
388
+ "offset": 0
389
+ }
390
}
349
- , "out": {
350
- "oid": ".1.3.6.1.2.1.2.2.1.16.",
351
- "algorithm": "incremental",
352
- "multiplier": -8,
353
- "divisor": 1024,
354
- "offset": 0
391
+ },
392
+ "snmp_switch.bandwidth_port": {
393
+ "title": "Switch Bandwidth for port ",
394
+ "titleoid": ".1.3.6.1.2.1.31.1.1.1.18.",
395
+ "units": "kilobits/s",
396
+ "type": "area",
397
+ "priority": 100,
398
+ "family": "ports",
399
+ "multiply_range": [
400
+ 1,
401
+ 24
402
+ ],
403
+ "dimensions": {
404
+ "in": {
405
+ "oid": ".1.3.6.1.2.1.2.2.1.10.",
406
+ "algorithm": "incremental",
407
+ "multiplier": 8,
408
+ "divisor": 1024,
409
+ "offset": 0
410
+ },
411
+ "out": {
412
+ "oid": ".1.3.6.1.2.1.2.2.1.16.",
413
+ "algorithm": "incremental",
414
+ "multiplier": -8,
415
+ "divisor": 1024,
416
+ "offset": 0
417
+ }
418
}
419
}
420
}
421
}
359
- }],
422
+ ]
423
}
424
```
425
collectors/node.d.plugin/snmp/snmp.node.js
+16
-4
@@ -341,11 +341,23 @@ netdata.processors.snmp = {
341
// no SNMP session has been created for this service
342
// the SNMP session is just the initialization of NET-SNMP
343
344
- if(__DEBUG === true)
345
- netdata.debug(service.module.name + ': ' + service.name + ': opening ' + this.name + ' session on ' + service.request.hostname + ' community ' + service.request.community + ' options ' + netdata.stringify(service.request.options));
344
+ var snmp_version = (service.request.options && service.request.options.version)
345
+ ? service.request.options.version
346
+ : net_snmp.Version1;
347
+
348
+ if(snmp_version === net_snmp.Version3) {
349
+ if(__DEBUG === true)
350
+ netdata.debug(service.module.name + ': ' + service.name + ': opening ' + this.name + ' session on ' + service.request.hostname + ' user ' + service.request.user + ' options ' + netdata.stringify(service.request.options));
351
347
- // create the SNMP session
348
- service.snmp_session = net_snmp.createSession (service.request.hostname, service.request.community, service.request.options);
352
+ // create the SNMP session
353
+ service.snmp_session = net_snmp.createV3Session (service.request.hostname, service.request.user, service.request.options);
354
+ } else {
355
+ if(__DEBUG === true)
356
+ netdata.debug(service.module.name + ': ' + service.name + ': opening ' + this.name + ' session on ' + service.request.hostname + ' community ' + service.request.community + ' options ' + netdata.stringify(service.request.options));
357
+
358
+ // create the SNMP session
359
+ service.snmp_session = net_snmp.createSession (service.request.hostname, service.request.community, service.request.options);
360
+ }
361
362
if(__DEBUG === true)
363
netdata.debug(service.module.name + ': ' + service.name + ': got ' + this.name + ' session: ' + netdata.stringify(service.snmp_session));