net-snmp 1.2.4 → 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,1464 +1,1464 @@
1
-
2
- // Copyright 2013 Stephen Vickers <stephen.vickers.sv@gmail.com>
3
-
4
- var ber = require ("asn1-ber").Ber;
5
- var dgram = require ("dgram");
6
- var events = require ("events");
7
- var util = require ("util");
8
-
9
- /*****************************************************************************
10
- ** Constants
11
- **/
12
-
13
- function _expandConstantObject (object) {
14
- var keys = [];
15
- for (var key in object)
16
- keys.push (key);
17
- for (var i = 0; i < keys.length; i++)
18
- object[object[keys[i]]] = parseInt (keys[i]);
19
- }
20
-
21
- var ErrorStatus = {
22
- 0: "NoError",
23
- 1: "TooBig",
24
- 2: "NoSuchName",
25
- 3: "BadValue",
26
- 4: "ReadOnly",
27
- 5: "GeneralError",
28
- 6: "NoAccess",
29
- 7: "WrongType",
30
- 8: "WrongLength",
31
- 9: "WrongEncoding",
32
- 10: "WrongValue",
33
- 11: "NoCreation",
34
- 12: "InconsistentValue",
35
- 13: "ResourceUnavailable",
36
- 14: "CommitFailed",
37
- 15: "UndoFailed",
38
- 16: "AuthorizationError",
39
- 17: "NotWritable",
40
- 18: "InconsistentName"
41
- };
42
-
43
- _expandConstantObject (ErrorStatus);
44
-
45
- var ObjectType = {
46
- 1: "Boolean",
47
- 2: "Integer",
48
- 4: "OctetString",
49
- 5: "Null",
50
- 6: "OID",
51
- 64: "IpAddress",
52
- 65: "Counter",
53
- 66: "Gauge",
54
- 67: "TimeTicks",
55
- 68: "Opaque",
56
- 70: "Counter64",
57
- 128: "NoSuchObject",
58
- 129: "NoSuchInstance",
59
- 130: "EndOfMibView"
60
- };
61
-
62
- _expandConstantObject (ObjectType);
63
-
64
- ObjectType.Integer32 = ObjectType.Integer;
65
- ObjectType.Counter32 = ObjectType.Counter;
66
- ObjectType.Gauge32 = ObjectType.Gauge;
67
- ObjectType.Unsigned32 = ObjectType.Gauge32;
68
-
69
- var PduType = {
70
- 160: "GetRequest",
71
- 161: "GetNextRequest",
72
- 162: "GetResponse",
73
- 163: "SetRequest",
74
- 164: "Trap",
75
- 165: "GetBulkRequest",
76
- 166: "InformRequest",
77
- 167: "TrapV2",
78
- 168: "Report"
79
- };
80
-
81
- _expandConstantObject (PduType);
82
-
83
- var TrapType = {
84
- 0: "ColdStart",
85
- 1: "WarmStart",
86
- 2: "LinkDown",
87
- 3: "LinkUp",
88
- 4: "AuthenticationFailure",
89
- 5: "EgpNeighborLoss",
90
- 6: "EnterpriseSpecific"
91
- };
92
-
93
- _expandConstantObject (TrapType);
94
-
95
- var Version1 = 0;
96
- var Version2c = 1;
97
-
98
- /*****************************************************************************
99
- ** Exception class definitions
100
- **/
101
-
102
- function ResponseInvalidError (message) {
103
- this.name = "ResponseInvalidError";
104
- this.message = message;
105
- Error.captureStackTrace(this, ResponseInvalidError);
106
- }
107
- util.inherits (ResponseInvalidError, Error);
108
-
109
- function RequestInvalidError (message) {
110
- this.name = "RequestInvalidError";
111
- this.message = message;
112
- Error.captureStackTrace(this, RequestInvalidError);
113
- }
114
- util.inherits (RequestInvalidError, Error);
115
-
116
- function RequestFailedError (message, status) {
117
- this.name = "RequestFailedError";
118
- this.message = message;
119
- this.status = status;
120
- Error.captureStackTrace(this, RequestFailedError);
121
- }
122
- util.inherits (RequestFailedError, Error);
123
-
124
- function RequestTimedOutError (message) {
125
- this.name = "RequestTimedOutError";
126
- this.message = message;
127
- Error.captureStackTrace(this, RequestTimedOutError);
128
- }
129
- util.inherits (RequestTimedOutError, Error);
130
-
131
- /*****************************************************************************
132
- ** OID and varbind helper functions
133
- **/
134
-
135
- function isVarbindError (varbind) {
136
- return !!(varbind.type == ObjectType.NoSuchObject
137
- || varbind.type == ObjectType.NoSuchInstance
138
- || varbind.type == ObjectType.EndOfMibView);
139
- }
140
-
141
- function varbindError (varbind) {
142
- return (ObjectType[varbind.type] || "NotAnError") + ": " + varbind.oid;
143
- }
144
-
145
- function oidFollowsOid (oidString, nextString) {
146
- var oid = {str: oidString, len: oidString.length, idx: 0};
147
- var next = {str: nextString, len: nextString.length, idx: 0};
148
- var dotCharCode = ".".charCodeAt (0);
149
-
150
- function getNumber (item) {
151
- var n = 0;
152
- if (item.idx >= item.len)
153
- return null;
154
- while (item.idx < item.len) {
155
- var charCode = item.str.charCodeAt (item.idx++);
156
- if (charCode == dotCharCode)
157
- return n;
158
- n = (n ? (n * 10) : n) + (charCode - 48);
159
- }
160
- return n;
161
- }
162
-
163
- while (1) {
164
- var oidNumber = getNumber (oid);
165
- var nextNumber = getNumber (next);
166
-
167
- if (oidNumber !== null) {
168
- if (nextNumber !== null) {
169
- if (nextNumber > oidNumber) {
170
- return true;
171
- } else if (nextNumber < oidNumber) {
172
- return false;
173
- }
174
- } else {
175
- return true;
176
- }
177
- } else {
178
- return true;
179
- }
180
- }
181
- }
182
-
183
- function oidInSubtree (oidString, nextString) {
184
- var oid = oidString.split (".");
185
- var next = nextString.split (".");
186
-
187
- if (oid.length > next.length)
188
- return false;
189
-
190
- for (var i = 0; i < oid.length; i++) {
191
- if (next[i] != oid[i])
192
- return false;
193
- }
194
-
195
- return true;
196
- }
197
-
198
- /**
199
- ** Some SNMP agents produce integers on the wire such as 00 ff ff ff ff.
200
- ** The ASN.1 BER parser we use throws an error when parsing this, which we
201
- ** believe is correct. So, we decided not to bother the "asn1" developer(s)
202
- ** with this, instead opting to work around it here.
203
- **
204
- ** If an integer is 5 bytes in length we check if the first byte is 0, and if so
205
- ** simply drop it and parse it like it was a 4 byte integer, otherwise throw
206
- ** an error since the integer is too large.
207
- **/
208
-
209
- function readInt (buffer) {
210
- return readUint (buffer, true);
211
- }
212
-
213
- function readUint (buffer, isSigned) {
214
- buffer.readByte ();
215
- var length = buffer.readByte ();
216
- var value = 0;
217
- var signedBitSet = false;
218
-
219
- if (length > 5) {
220
- throw new RangeError ("Integer too long '" + length + "'");
221
- } else if (length == 5) {
222
- if (buffer.readByte () !== 0)
223
- throw new RangeError ("Integer too long '" + length + "'");
224
- length = 4;
225
- }
226
-
227
- for (var i = 0; i < length; i++) {
228
- value *= 256;
229
- value += buffer.readByte ();
230
-
231
- if (isSigned && i <= 0) {
232
- if ((value & 0x80) == 0x80)
233
- signedBitSet = true;
234
- }
235
- }
236
-
237
- if (signedBitSet)
238
- value -= (1 << (i * 8));
239
-
240
- return value;
241
- }
242
-
243
- function readUint64 (buffer) {
244
- var value = buffer.readString (ObjectType.Counter64, true);
245
-
246
- return value;
247
- }
248
-
249
- function readVarbinds (buffer, varbinds) {
250
- buffer.readSequence ();
251
-
252
- while (1) {
253
- buffer.readSequence ();
254
- var oid = buffer.readOID ();
255
- var type = buffer.peek ();
256
-
257
- if (type == null)
258
- break;
259
-
260
- var value;
261
-
262
- if (type == ObjectType.Boolean) {
263
- value = buffer.readBoolean ();
264
- } else if (type == ObjectType.Integer) {
265
- value = readInt (buffer);
266
- } else if (type == ObjectType.OctetString) {
267
- value = buffer.readString (null, true);
268
- } else if (type == ObjectType.Null) {
269
- buffer.readByte ();
270
- buffer.readByte ();
271
- value = null;
272
- } else if (type == ObjectType.OID) {
273
- value = buffer.readOID ();
274
- } else if (type == ObjectType.IpAddress) {
275
- var bytes = buffer.readString (ObjectType.IpAddress, true);
276
- if (bytes.length != 4)
277
- throw new ResponseInvalidError ("Length '" + bytes.length
278
- + "' of IP address '" + bytes.toString ("hex")
279
- + "' is not 4");
280
- value = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
281
- } else if (type == ObjectType.Counter) {
282
- value = readUint (buffer);
283
- } else if (type == ObjectType.Gauge) {
284
- value = readUint (buffer);
285
- } else if (type == ObjectType.TimeTicks) {
286
- value = readUint (buffer);
287
- } else if (type == ObjectType.Opaque) {
288
- value = buffer.readString (ObjectType.Opaque, true);
289
- } else if (type == ObjectType.Counter64) {
290
- value = readUint64 (buffer);
291
- } else if (type == ObjectType.NoSuchObject) {
292
- buffer.readByte ();
293
- buffer.readByte ();
294
- value = null;
295
- } else if (type == ObjectType.NoSuchInstance) {
296
- buffer.readByte ();
297
- buffer.readByte ();
298
- value = null;
299
- } else if (type == ObjectType.EndOfMibView) {
300
- buffer.readByte ();
301
- buffer.readByte ();
302
- value = null;
303
- } else {
304
- throw new ResponseInvalidError ("Unknown type '" + type
305
- + "' in response");
306
- }
307
-
308
- varbinds.push ({
309
- oid: oid,
310
- type: type,
311
- value: value
312
- });
313
- }
314
- }
315
-
316
- function writeUint (buffer, type, value) {
317
- var b = new Buffer (4);
318
- b.writeUInt32BE (value, 0);
319
- buffer.writeBuffer (b, type);
320
- }
321
-
322
- function writeUint64 (buffer, value) {
323
- buffer.writeBuffer (value, ObjectType.Counter64);
324
- }
325
-
326
- function writeVarbinds (buffer, varbinds) {
327
- buffer.startSequence ();
328
- for (var i = 0; i < varbinds.length; i++) {
329
- buffer.startSequence ();
330
- buffer.writeOID (varbinds[i].oid);
331
-
332
- if (varbinds[i].type && varbinds[i].hasOwnProperty("value")) {
333
- var type = varbinds[i].type;
334
- var value = varbinds[i].value;
335
-
336
- if (type == ObjectType.Boolean) {
337
- buffer.writeBoolean (value ? true : false);
338
- } else if (type == ObjectType.Integer) { // also Integer32
339
- buffer.writeInt (value);
340
- } else if (type == ObjectType.OctetString) {
341
- if (typeof value == "string")
342
- buffer.writeString (value);
343
- else
344
- buffer.writeBuffer (value, ObjectType.OctetString);
345
- } else if (type == ObjectType.Null) {
346
- buffer.writeNull ();
347
- } else if (type == ObjectType.OID) {
348
- buffer.writeOID (value);
349
- } else if (type == ObjectType.IpAddress) {
350
- var bytes = value.split (".");
351
- if (bytes.length != 4)
352
- throw new RequestInvalidError ("Invalid IP address '"
353
- + value + "'");
354
- buffer.writeBuffer (new Buffer (bytes), 64);
355
- } else if (type == ObjectType.Counter) { // also Counter32
356
- writeUint (buffer, ObjectType.Counter, value);
357
- } else if (type == ObjectType.Gauge) { // also Gauge32 & Unsigned32
358
- writeUint (buffer, ObjectType.Gauge, value);
359
- } else if (type == ObjectType.TimeTicks) {
360
- writeUint (buffer, ObjectType.TimeTicks, value);
361
- } else if (type == ObjectType.Opaque) {
362
- buffer.writeBuffer (value, ObjectType.Opaque);
363
- } else if (type == ObjectType.Counter64) {
364
- writeUint64 (buffer, value);
365
- } else {
366
- throw new RequestInvalidError ("Unknown type '" + type
367
- + "' in request");
368
- }
369
- } else {
370
- buffer.writeNull ();
371
- }
372
-
373
- buffer.endSequence ();
374
- }
375
- buffer.endSequence ();
376
- }
377
-
378
- /*****************************************************************************
379
- ** PDU class definitions
380
- **/
381
-
382
- var SimplePdu = function (id, varbinds, options) {
383
- this.id = id;
384
- this.varbinds = varbinds;
385
- this.options = options || {};
386
- };
387
-
388
- SimplePdu.prototype.toBuffer = function (buffer) {
389
- buffer.startSequence (this.type);
390
-
391
- buffer.writeInt (this.id);
392
- buffer.writeInt ((this.type == PduType.GetBulkRequest)
393
- ? (this.options.nonRepeaters || 0)
394
- : 0);
395
- buffer.writeInt ((this.type == PduType.GetBulkRequest)
396
- ? (this.options.maxRepetitions || 0)
397
- : 0);
398
-
399
- writeVarbinds (buffer, this.varbinds);
400
-
401
- buffer.endSequence ();
402
- };
403
-
404
- var GetBulkRequestPdu = function () {
405
- this.type = PduType.GetBulkRequest;
406
- GetBulkRequestPdu.super_.apply (this, arguments);
407
- };
408
-
409
- util.inherits (GetBulkRequestPdu, SimplePdu);
410
-
411
- var GetNextRequestPdu = function () {
412
- this.type = PduType.GetNextRequest;
413
- GetNextRequestPdu.super_.apply (this, arguments);
414
- };
415
-
416
- util.inherits (GetNextRequestPdu, SimplePdu);
417
-
418
- var GetResponsePdu = function (buffer) {
419
- this.type = PduType.GetResponse;
420
-
421
- buffer.readSequence (this.type);
422
-
423
- this.id = buffer.readInt ();
424
-
425
- this.errorStatus = buffer.readInt ();
426
- this.errorIndex = buffer.readInt ();
427
-
428
- this.varbinds = [];
429
-
430
- readVarbinds (buffer, this.varbinds);
431
- };
432
-
433
- var GetRequestPdu = function () {
434
- this.type = PduType.GetRequest;
435
- GetRequestPdu.super_.apply (this, arguments);
436
- };
437
-
438
- util.inherits (GetRequestPdu, SimplePdu);
439
-
440
- var InformRequestPdu = function () {
441
- this.type = PduType.InformRequest;
442
- InformRequestPdu.super_.apply (this, arguments);
443
- };
444
-
445
- util.inherits (InformRequestPdu, SimplePdu);
446
-
447
- var SetRequestPdu = function () {
448
- this.type = PduType.SetRequest;
449
- SetRequestPdu.super_.apply (this, arguments);
450
- };
451
-
452
- util.inherits (SetRequestPdu, SimplePdu);
453
-
454
- var TrapPdu = function (typeOrOid, varbinds, options) {
455
- this.type = PduType.Trap;
456
-
457
- this.agentAddr = options.agentAddr || "127.0.0.1";
458
- this.upTime = options.upTime;
459
-
460
- if (typeof typeOrOid == "string") {
461
- this.generic = TrapType.EnterpriseSpecific;
462
- this.specific = parseInt (typeOrOid.match (/\.(\d+)$/)[1]);
463
- this.enterprise = typeOrOid.replace (/\.(\d+)$/, "");
464
- } else {
465
- this.generic = typeOrOid;
466
- this.specific = 0;
467
- this.enterprise = "1.3.6.1.4.1";
468
- }
469
-
470
- this.varbinds = varbinds;
471
- };
472
-
473
- TrapPdu.prototype.toBuffer = function (buffer) {
474
- buffer.startSequence (this.type);
475
-
476
- buffer.writeOID (this.enterprise);
477
- buffer.writeBuffer (new Buffer (this.agentAddr.split (".")),
478
- ObjectType.IpAddress);
479
- buffer.writeInt (this.generic);
480
- buffer.writeInt (this.specific);
481
- writeUint (buffer, ObjectType.TimeTicks,
482
- this.upTime || Math.floor (process.uptime () * 100));
483
-
484
- writeVarbinds (buffer, this.varbinds);
485
-
486
- buffer.endSequence ();
487
- };
488
-
489
- var TrapV2Pdu = function () {
490
- this.type = PduType.TrapV2;
491
- TrapV2Pdu.super_.apply (this, arguments);
492
- };
493
-
494
- util.inherits (TrapV2Pdu, SimplePdu);
495
-
496
- /*****************************************************************************
497
- ** Message class definitions
498
- **/
499
-
500
- var RequestMessage = function (version, community, pdu) {
501
- this.version = version;
502
- this.community = community;
503
- this.pdu = pdu;
504
- };
505
-
506
- RequestMessage.prototype.toBuffer = function () {
507
- if (this.buffer)
508
- return this.buffer;
509
-
510
- var writer = new ber.Writer ();
511
-
512
- writer.startSequence ();
513
-
514
- writer.writeInt (this.version);
515
- writer.writeString (this.community);
516
-
517
- this.pdu.toBuffer (writer);
518
-
519
- writer.endSequence ();
520
-
521
- this.buffer = writer.buffer;
522
-
523
- return this.buffer;
524
- };
525
-
526
- var ResponseMessage = function (buffer) {
527
- var reader = new ber.Reader (buffer);
528
-
529
- reader.readSequence ();
530
-
531
- this.version = reader.readInt ();
532
- this.community = reader.readString ();
533
-
534
- var type = reader.peek ();
535
-
536
- if (type == PduType.GetResponse) {
537
- this.pdu = new GetResponsePdu (reader);
538
- } else {
539
- throw new ResponseInvalidError ("Unknown PDU type '" + type
540
- + "' in response");
541
- }
542
- };
543
-
544
- /*****************************************************************************
545
- ** Session class definition
546
- **/
547
-
548
- var Session = function (target, community, options) {
549
- this.target = target || "127.0.0.1";
550
- this.community = community || "public";
551
-
552
- this.version = (options && options.version)
553
- ? options.version
554
- : Version1;
555
-
556
- this.transport = (options && options.transport)
557
- ? options.transport
558
- : "udp4";
559
- this.port = (options && options.port )
560
- ? options.port
561
- : 161;
562
- this.trapPort = (options && options.trapPort )
563
- ? options.trapPort
564
- : 162;
565
-
566
- this.retries = (options && (options.retries || options.retries == 0))
567
- ? options.retries
568
- : 1;
569
- this.timeout = (options && options.timeout)
570
- ? options.timeout
571
- : 5000;
572
-
573
- this.sourceAddress = (options && options.sourceAddress )
574
- ? options.sourceAddress
575
- : undefined;
576
- this.sourcePort = (options && options.sourcePort )
577
- ? parseInt(options.sourcePort)
578
- : undefined;
579
-
580
- this.idBitsSize = (options && options.idBitsSize)
581
- ? parseInt(options.idBitsSize)
582
- : 32;
583
-
584
- this.reqs = {};
585
- this.reqCount = 0;
586
-
587
- this.dgram = dgram.createSocket (this.transport);
588
- this.dgram.unref();
589
-
590
- var me = this;
591
- this.dgram.on ("message", me.onMsg.bind (me));
592
- this.dgram.on ("close", me.onClose.bind (me));
593
- this.dgram.on ("error", me.onError.bind (me));
594
-
595
- if (this.sourceAddress || this.sourcePort)
596
- this.dgram.bind (this.sourcePort, this.sourceAddress);
597
- };
598
-
599
- util.inherits (Session, events.EventEmitter);
600
-
601
- Session.prototype.close = function () {
602
- this.dgram.close ();
603
- return this;
604
- };
605
-
606
- Session.prototype.cancelRequests = function (error) {
607
- var id;
608
- for (id in this.reqs) {
609
- var req = this.reqs[id];
610
- this.unregisterRequest (req.id);
611
- req.responseCb (error);
612
- }
613
- };
614
-
615
- function _generateId (bitSize) {
616
- if (bitSize === 16) {
617
- return Math.floor(Math.random() * 10000) % 65535;
618
- }
619
- return Math.floor(Math.random() * 100000000) % 4294967295;
620
- }
621
-
622
- Session.prototype.get = function (oids, responseCb) {
623
- function feedCb (req, message) {
624
- var pdu = message.pdu;
625
- var varbinds = [];
626
-
627
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
628
- req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
629
- + "match response OIDs"));
630
- } else {
631
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
632
- if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
633
- req.responseCb (new ResponseInvalidError ("OID '"
634
- + req.message.pdu.varbinds[i].oid
635
- + "' in request at positiion '" + i + "' does not "
636
- + "match OID '" + pdu.varbinds[i].oid + "' in response "
637
- + "at position '" + i + "'"));
638
- return;
639
- } else {
640
- varbinds.push (pdu.varbinds[i]);
641
- }
642
- }
643
-
644
- req.responseCb (null, varbinds);
645
- }
646
- }
647
-
648
- var pduVarbinds = [];
649
-
650
- for (var i = 0; i < oids.length; i++) {
651
- var varbind = {
652
- oid: oids[i]
653
- };
654
- pduVarbinds.push (varbind);
655
- }
656
-
657
- this.simpleGet (GetRequestPdu, feedCb, pduVarbinds, responseCb);
658
-
659
- return this;
660
- };
661
-
662
- Session.prototype.getBulk = function () {
663
- var oids, nonRepeaters, maxRepetitions, responseCb;
664
-
665
- if (arguments.length >= 4) {
666
- oids = arguments[0];
667
- nonRepeaters = arguments[1];
668
- maxRepetitions = arguments[2];
669
- responseCb = arguments[3];
670
- } else if (arguments.length >= 3) {
671
- oids = arguments[0];
672
- nonRepeaters = arguments[1];
673
- maxRepetitions = 10;
674
- responseCb = arguments[2];
675
- } else {
676
- oids = arguments[0];
677
- nonRepeaters = 0;
678
- maxRepetitions = 10;
679
- responseCb = arguments[1];
680
- }
681
-
682
- function feedCb (req, message) {
683
- var pdu = message.pdu;
684
- var varbinds = [];
685
- var i = 0;
686
-
687
- // first walk through and grab non-repeaters
688
- if (pdu.varbinds.length < nonRepeaters) {
689
- req.responseCb (new ResponseInvalidError ("Varbind count in "
690
- + "response '" + pdu.varbinds.length + "' is less than "
691
- + "non-repeaters '" + nonRepeaters + "' in request"));
692
- } else {
693
- for ( ; i < nonRepeaters; i++) {
694
- if (isVarbindError (pdu.varbinds[i])) {
695
- varbinds.push (pdu.varbinds[i]);
696
- } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
697
- pdu.varbinds[i].oid)) {
698
- req.responseCb (new ResponseInvalidError ("OID '"
699
- + req.message.pdu.varbinds[i].oid + "' in request at "
700
- + "positiion '" + i + "' does not precede "
701
- + "OID '" + pdu.varbinds[i].oid + "' in response "
702
- + "at position '" + i + "'"));
703
- return;
704
- } else {
705
- varbinds.push (pdu.varbinds[i]);
706
- }
707
- }
708
- }
709
-
710
- var repeaters = req.message.pdu.varbinds.length - nonRepeaters;
711
-
712
- // secondly walk through and grab repeaters
713
- if (pdu.varbinds.length % (repeaters)) {
714
- req.responseCb (new ResponseInvalidError ("Varbind count in "
715
- + "response '" + pdu.varbinds.length + "' is not a "
716
- + "multiple of repeaters '" + repeaters
717
- + "' plus non-repeaters '" + nonRepeaters + "' in request"));
718
- } else {
719
- while (i < pdu.varbinds.length) {
720
- for (var j = 0; j < repeaters; j++, i++) {
721
- var reqIndex = nonRepeaters + j;
722
- var respIndex = i;
723
-
724
- if (isVarbindError (pdu.varbinds[respIndex])) {
725
- if (! varbinds[reqIndex])
726
- varbinds[reqIndex] = [];
727
- varbinds[reqIndex].push (pdu.varbinds[respIndex]);
728
- } else if (! oidFollowsOid (
729
- req.message.pdu.varbinds[reqIndex].oid,
730
- pdu.varbinds[respIndex].oid)) {
731
- req.responseCb (new ResponseInvalidError ("OID '"
732
- + req.message.pdu.varbinds[reqIndex].oid
733
- + "' in request at positiion '" + (reqIndex)
734
- + "' does not precede OID '"
735
- + pdu.varbinds[respIndex].oid
736
- + "' in response at position '" + (respIndex) + "'"));
737
- return;
738
- } else {
739
- if (! varbinds[reqIndex])
740
- varbinds[reqIndex] = [];
741
- varbinds[reqIndex].push (pdu.varbinds[respIndex]);
742
- }
743
- }
744
- }
745
- }
746
-
747
- req.responseCb (null, varbinds);
748
- }
749
-
750
- var pduVarbinds = [];
751
-
752
- for (var i = 0; i < oids.length; i++) {
753
- var varbind = {
754
- oid: oids[i]
755
- };
756
- pduVarbinds.push (varbind);
757
- }
758
-
759
- var options = {
760
- nonRepeaters: nonRepeaters,
761
- maxRepetitions: maxRepetitions
762
- };
763
-
764
- this.simpleGet (GetBulkRequestPdu, feedCb, pduVarbinds, responseCb,
765
- options);
766
-
767
- return this;
768
- };
769
-
770
- Session.prototype.getNext = function (oids, responseCb) {
771
- function feedCb (req, message) {
772
- var pdu = message.pdu;
773
- var varbinds = [];
774
-
775
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
776
- req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
777
- + "match response OIDs"));
778
- } else {
779
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
780
- if (isVarbindError (pdu.varbinds[i])) {
781
- varbinds.push (pdu.varbinds[i]);
782
- } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
783
- pdu.varbinds[i].oid)) {
784
- req.responseCb (new ResponseInvalidError ("OID '"
785
- + req.message.pdu.varbinds[i].oid + "' in request at "
786
- + "positiion '" + i + "' does not precede "
787
- + "OID '" + pdu.varbinds[i].oid + "' in response "
788
- + "at position '" + i + "'"));
789
- return;
790
- } else {
791
- varbinds.push (pdu.varbinds[i]);
792
- }
793
- }
794
-
795
- req.responseCb (null, varbinds);
796
- }
797
- }
798
-
799
- var pduVarbinds = [];
800
-
801
- for (var i = 0; i < oids.length; i++) {
802
- var varbind = {
803
- oid: oids[i]
804
- };
805
- pduVarbinds.push (varbind);
806
- }
807
-
808
- this.simpleGet (GetNextRequestPdu, feedCb, pduVarbinds, responseCb);
809
-
810
- return this;
811
- };
812
-
813
- Session.prototype.inform = function () {
814
- var typeOrOid = arguments[0];
815
- var varbinds, options = {}, responseCb;
816
-
817
- /**
818
- ** Support the following signatures:
819
- **
820
- ** typeOrOid, varbinds, options, callback
821
- ** typeOrOid, varbinds, callback
822
- ** typeOrOid, options, callback
823
- ** typeOrOid, callback
824
- **/
825
- if (arguments.length >= 4) {
826
- varbinds = arguments[1];
827
- options = arguments[2];
828
- responseCb = arguments[3];
829
- } else if (arguments.length >= 3) {
830
- if (arguments[1].constructor != Array) {
831
- varbinds = [];
832
- options = arguments[1];
833
- responseCb = arguments[2];
834
- } else {
835
- varbinds = arguments[1];
836
- responseCb = arguments[2];
837
- }
838
- } else {
839
- varbinds = [];
840
- responseCb = arguments[1];
841
- }
842
-
843
- function feedCb (req, message) {
844
- var pdu = message.pdu;
845
- var varbinds = [];
846
-
847
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
848
- req.responseCb (new ResponseInvalidError ("Inform OIDs do not "
849
- + "match response OIDs"));
850
- } else {
851
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
852
- if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
853
- req.responseCb (new ResponseInvalidError ("OID '"
854
- + req.message.pdu.varbinds[i].oid
855
- + "' in inform at positiion '" + i + "' does not "
856
- + "match OID '" + pdu.varbinds[i].oid + "' in response "
857
- + "at position '" + i + "'"));
858
- return;
859
- } else {
860
- varbinds.push (pdu.varbinds[i]);
861
- }
862
- }
863
-
864
- req.responseCb (null, varbinds);
865
- }
866
- }
867
-
868
- if (typeof typeOrOid != "string")
869
- typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
870
-
871
- var pduVarbinds = [
872
- {
873
- oid: "1.3.6.1.2.1.1.3.0",
874
- type: ObjectType.TimeTicks,
875
- value: options.upTime || Math.floor (process.uptime () * 100)
876
- },
877
- {
878
- oid: "1.3.6.1.6.3.1.1.4.1.0",
879
- type: ObjectType.OID,
880
- value: typeOrOid
881
- }
882
- ];
883
-
884
- for (var i = 0; i < varbinds.length; i++) {
885
- var varbind = {
886
- oid: varbinds[i].oid,
887
- type: varbinds[i].type,
888
- value: varbinds[i].value
889
- };
890
- pduVarbinds.push (varbind);
891
- }
892
-
893
- options.port = this.trapPort;
894
-
895
- this.simpleGet (InformRequestPdu, feedCb, pduVarbinds, responseCb, options);
896
-
897
- return this;
898
- };
899
-
900
- Session.prototype.onClose = function () {
901
- this.cancelRequests (new Error ("Socket forcibly closed"));
902
- this.emit ("close");
903
- };
904
-
905
- Session.prototype.onError = function (error) {
906
- this.emit (error);
907
- };
908
-
909
- Session.prototype.onMsg = function (buffer, remote) {
910
- try {
911
- var message = new ResponseMessage (buffer);
912
-
913
- var req = this.unregisterRequest (message.pdu.id);
914
- if (! req)
915
- return;
916
-
917
- try {
918
- if (message.version != req.message.version) {
919
- req.responseCb (new ResponseInvalidError ("Version in request '"
920
- + req.message.version + "' does not match version in "
921
- + "response '" + message.version));
922
- } else if (message.community != req.message.community) {
923
- req.responseCb (new ResponseInvalidError ("Community '"
924
- + req.message.community + "' in request does not match "
925
- + "community '" + message.community + "' in response"));
926
- } else if (message.pdu.type == PduType.GetResponse) {
927
- req.onResponse (req, message);
928
- } else {
929
- req.responseCb (new ResponseInvalidError ("Unknown PDU type '"
930
- + message.pdu.type + "' in response"));
931
- }
932
- } catch (error) {
933
- req.responseCb (error);
934
- }
935
- } catch (error) {
936
- this.emit("error", error);
937
- }
938
- };
939
-
940
- Session.prototype.onSimpleGetResponse = function (req, message) {
941
- var pdu = message.pdu;
942
-
943
- if (pdu.errorStatus > 0) {
944
- var statusString = ErrorStatus[pdu.errorStatus]
945
- || ErrorStatus.GeneralError;
946
- var statusCode = ErrorStatus[statusString]
947
- || ErrorStatus[ErrorStatus.GeneralError];
948
-
949
- if (pdu.errorIndex <= 0 || pdu.errorIndex > pdu.varbinds.length) {
950
- req.responseCb (new RequestFailedError (statusString, statusCode));
951
- } else {
952
- var oid = pdu.varbinds[pdu.errorIndex - 1].oid;
953
- var error = new RequestFailedError (statusString + ": " + oid,
954
- statusCode);
955
- req.responseCb (error);
956
- }
957
- } else {
958
- req.feedCb (req, message);
959
- }
960
- };
961
-
962
- Session.prototype.registerRequest = function (req) {
963
- if (! this.reqs[req.id]) {
964
- this.reqs[req.id] = req;
965
- if (this.reqCount <= 0)
966
- this.dgram.ref();
967
- this.reqCount++;
968
- }
969
- var me = this;
970
- req.timer = setTimeout (function () {
971
- if (req.retries-- > 0) {
972
- me.send (req);
973
- } else {
974
- me.unregisterRequest (req.id);
975
- req.responseCb (new RequestTimedOutError (
976
- "Request timed out"));
977
- }
978
- }, req.timeout);
979
- };
980
-
981
- Session.prototype.send = function (req, noWait) {
982
- try {
983
- var me = this;
984
-
985
- var buffer = req.message.toBuffer ();
986
-
987
- this.dgram.send (buffer, 0, buffer.length, req.port, this.target,
988
- function (error, bytes) {
989
- if (error) {
990
- req.responseCb (error);
991
- } else {
992
- if (noWait) {
993
- req.responseCb (null);
994
- } else {
995
- me.registerRequest (req);
996
- }
997
- }
998
- });
999
- } catch (error) {
1000
- req.responseCb (error);
1001
- }
1002
-
1003
- return this;
1004
- };
1005
-
1006
- Session.prototype.set = function (varbinds, responseCb) {
1007
- function feedCb (req, message) {
1008
- var pdu = message.pdu;
1009
- var varbinds = [];
1010
-
1011
- if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1012
- req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
1013
- + "match response OIDs"));
1014
- } else {
1015
- for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1016
- if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1017
- req.responseCb (new ResponseInvalidError ("OID '"
1018
- + req.message.pdu.varbinds[i].oid
1019
- + "' in request at positiion '" + i + "' does not "
1020
- + "match OID '" + pdu.varbinds[i].oid + "' in response "
1021
- + "at position '" + i + "'"));
1022
- return;
1023
- } else {
1024
- varbinds.push (pdu.varbinds[i]);
1025
- }
1026
- }
1027
-
1028
- req.responseCb (null, varbinds);
1029
- }
1030
- }
1031
-
1032
- var pduVarbinds = [];
1033
-
1034
- for (var i = 0; i < varbinds.length; i++) {
1035
- var varbind = {
1036
- oid: varbinds[i].oid,
1037
- type: varbinds[i].type,
1038
- value: varbinds[i].value
1039
- };
1040
- pduVarbinds.push (varbind);
1041
- }
1042
-
1043
- this.simpleGet (SetRequestPdu, feedCb, pduVarbinds, responseCb);
1044
-
1045
- return this;
1046
- };
1047
-
1048
- Session.prototype.simpleGet = function (pduClass, feedCb, varbinds,
1049
- responseCb, options) {
1050
- var req = {};
1051
-
1052
- try {
1053
- var id = _generateId (this.idBitsSize);
1054
- var pdu = new pduClass (id, varbinds, options);
1055
- var message = new RequestMessage (this.version, this.community, pdu);
1056
-
1057
- req = {
1058
- id: id,
1059
- message: message,
1060
- responseCb: responseCb,
1061
- retries: this.retries,
1062
- timeout: this.timeout,
1063
- onResponse: this.onSimpleGetResponse,
1064
- feedCb: feedCb,
1065
- port: (options && options.port) ? options.port : this.port
1066
- };
1067
-
1068
- this.send (req);
1069
- } catch (error) {
1070
- if (req.responseCb)
1071
- req.responseCb (error);
1072
- }
1073
- };
1074
-
1075
- function subtreeCb (req, varbinds) {
1076
- var done = 0;
1077
-
1078
- for (var i = varbinds.length; i > 0; i--) {
1079
- if (! oidInSubtree (req.baseOid, varbinds[i - 1].oid)) {
1080
- done = 1;
1081
- varbinds.pop ();
1082
- }
1083
- }
1084
-
1085
- if (varbinds.length > 0)
1086
- req.feedCb (varbinds);
1087
-
1088
- if (done)
1089
- return true;
1090
- }
1091
-
1092
- Session.prototype.subtree = function () {
1093
- var me = this;
1094
- var oid = arguments[0];
1095
- var maxRepetitions, feedCb, doneCb;
1096
-
1097
- if (arguments.length < 4) {
1098
- maxRepetitions = 20;
1099
- feedCb = arguments[1];
1100
- doneCb = arguments[2];
1101
- } else {
1102
- maxRepetitions = arguments[1];
1103
- feedCb = arguments[2];
1104
- doneCb = arguments[3];
1105
- }
1106
-
1107
- var req = {
1108
- feedCb: feedCb,
1109
- doneCb: doneCb,
1110
- maxRepetitions: maxRepetitions,
1111
- baseOid: oid
1112
- };
1113
-
1114
- this.walk (oid, maxRepetitions, subtreeCb.bind (me, req), doneCb);
1115
-
1116
- return this;
1117
- };
1118
-
1119
- function tableColumnsResponseCb (req, error) {
1120
- if (error) {
1121
- req.responseCb (error);
1122
- } else if (req.error) {
1123
- req.responseCb (req.error);
1124
- } else {
1125
- if (req.columns.length > 0) {
1126
- var column = req.columns.pop ();
1127
- var me = this;
1128
- this.subtree (req.rowOid + column, req.maxRepetitions,
1129
- tableColumnsFeedCb.bind (me, req),
1130
- tableColumnsResponseCb.bind (me, req));
1131
- } else {
1132
- req.responseCb (null, req.table);
1133
- }
1134
- }
1135
- }
1136
-
1137
- function tableColumnsFeedCb (req, varbinds) {
1138
- for (var i = 0; i < varbinds.length; i++) {
1139
- if (isVarbindError (varbinds[i])) {
1140
- req.error = new RequestFailedError (varbindError (varbind[i]));
1141
- return true;
1142
- }
1143
-
1144
- var oid = varbinds[i].oid.replace (req.rowOid, "");
1145
- if (oid && oid != varbinds[i].oid) {
1146
- var match = oid.match (/^(\d+)\.(.+)$/);
1147
- if (match && match[1] > 0) {
1148
- if (! req.table[match[2]])
1149
- req.table[match[2]] = {};
1150
- req.table[match[2]][match[1]] = varbinds[i].value;
1151
- }
1152
- }
1153
- }
1154
- }
1155
-
1156
- Session.prototype.tableColumns = function () {
1157
- var me = this;
1158
-
1159
- var oid = arguments[0];
1160
- var columns = arguments[1];
1161
- var maxRepetitions, responseCb;
1162
-
1163
- if (arguments.length < 4) {
1164
- responseCb = arguments[2];
1165
- maxRepetitions = 20;
1166
- } else {
1167
- maxRepetitions = arguments[2];
1168
- responseCb = arguments[3];
1169
- }
1170
-
1171
- var req = {
1172
- responseCb: responseCb,
1173
- maxRepetitions: maxRepetitions,
1174
- baseOid: oid,
1175
- rowOid: oid + ".1.",
1176
- columns: columns.slice(0),
1177
- table: {}
1178
- };
1179
-
1180
- if (req.columns.length > 0) {
1181
- var column = req.columns.pop ();
1182
- this.subtree (req.rowOid + column, maxRepetitions,
1183
- tableColumnsFeedCb.bind (me, req),
1184
- tableColumnsResponseCb.bind (me, req));
1185
- }
1186
-
1187
- return this;
1188
- };
1189
-
1190
- function tableResponseCb (req, error) {
1191
- if (error)
1192
- req.responseCb (error);
1193
- else if (req.error)
1194
- req.responseCb (req.error);
1195
- else
1196
- req.responseCb (null, req.table);
1197
- }
1198
-
1199
- function tableFeedCb (req, varbinds) {
1200
- for (var i = 0; i < varbinds.length; i++) {
1201
- if (isVarbindError (varbinds[i])) {
1202
- req.error = new RequestFailedError (varbindError (varbind[i]));
1203
- return true;
1204
- }
1205
-
1206
- var oid = varbinds[i].oid.replace (req.rowOid, "");
1207
- if (oid && oid != varbinds[i].oid) {
1208
- var match = oid.match (/^(\d+)\.(.+)$/);
1209
- if (match && match[1] > 0) {
1210
- if (! req.table[match[2]])
1211
- req.table[match[2]] = {};
1212
- req.table[match[2]][match[1]] = varbinds[i].value;
1213
- }
1214
- }
1215
- }
1216
- }
1217
-
1218
- Session.prototype.table = function () {
1219
- var me = this;
1220
-
1221
- var oid = arguments[0];
1222
- var maxRepetitions, responseCb;
1223
-
1224
- if (arguments.length < 3) {
1225
- responseCb = arguments[1];
1226
- maxRepetitions = 20;
1227
- } else {
1228
- maxRepetitions = arguments[1];
1229
- responseCb = arguments[2];
1230
- }
1231
-
1232
- var req = {
1233
- responseCb: responseCb,
1234
- maxRepetitions: maxRepetitions,
1235
- baseOid: oid,
1236
- rowOid: oid + ".1.",
1237
- table: {}
1238
- };
1239
-
1240
- this.subtree (oid, maxRepetitions, tableFeedCb.bind (me, req),
1241
- tableResponseCb.bind (me, req));
1242
-
1243
- return this;
1244
- };
1245
-
1246
- Session.prototype.trap = function () {
1247
- var req = {};
1248
-
1249
- try {
1250
- var typeOrOid = arguments[0];
1251
- var varbinds, options = {}, responseCb;
1252
-
1253
- /**
1254
- ** Support the following signatures:
1255
- **
1256
- ** typeOrOid, varbinds, options, callback
1257
- ** typeOrOid, varbinds, agentAddr, callback
1258
- ** typeOrOid, varbinds, callback
1259
- ** typeOrOid, agentAddr, callback
1260
- ** typeOrOid, options, callback
1261
- ** typeOrOid, callback
1262
- **/
1263
- if (arguments.length >= 4) {
1264
- varbinds = arguments[1];
1265
- if (typeof arguments[2] == "string") {
1266
- options.agentAddr = arguments[2];
1267
- } else if (arguments[2].constructor != Array) {
1268
- options = arguments[2];
1269
- }
1270
- responseCb = arguments[3];
1271
- } else if (arguments.length >= 3) {
1272
- if (typeof arguments[1] == "string") {
1273
- varbinds = [];
1274
- options.agentAddr = arguments[1];
1275
- } else if (arguments[1].constructor != Array) {
1276
- varbinds = [];
1277
- options = arguments[1];
1278
- } else {
1279
- varbinds = arguments[1];
1280
- agentAddr = null;
1281
- }
1282
- responseCb = arguments[2];
1283
- } else {
1284
- varbinds = [];
1285
- responseCb = arguments[1];
1286
- }
1287
-
1288
- var pdu, pduVarbinds = [];
1289
-
1290
- for (var i = 0; i < varbinds.length; i++) {
1291
- var varbind = {
1292
- oid: varbinds[i].oid,
1293
- type: varbinds[i].type,
1294
- value: varbinds[i].value
1295
- };
1296
- pduVarbinds.push (varbind);
1297
- }
1298
-
1299
- var id = _generateId (this.idBitsSize);
1300
-
1301
- if (this.version == Version2c) {
1302
- if (typeof typeOrOid != "string")
1303
- typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
1304
-
1305
- pduVarbinds.unshift (
1306
- {
1307
- oid: "1.3.6.1.2.1.1.3.0",
1308
- type: ObjectType.TimeTicks,
1309
- value: options.upTime || Math.floor (process.uptime () * 100)
1310
- },
1311
- {
1312
- oid: "1.3.6.1.6.3.1.1.4.1.0",
1313
- type: ObjectType.OID,
1314
- value: typeOrOid
1315
- }
1316
- );
1317
-
1318
- pdu = new TrapV2Pdu (id, pduVarbinds, options);
1319
- } else {
1320
- pdu = new TrapPdu (typeOrOid, pduVarbinds, options);
1321
- }
1322
-
1323
- var message = new RequestMessage (this.version, this.community, pdu);
1324
-
1325
- req = {
1326
- id: id,
1327
- message: message,
1328
- responseCb: responseCb,
1329
- port: this.trapPort
1330
- };
1331
-
1332
- this.send (req, true);
1333
- } catch (error) {
1334
- if (req.responseCb)
1335
- req.responseCb (error);
1336
- }
1337
-
1338
- return this;
1339
- };
1340
-
1341
- Session.prototype.unregisterRequest = function (id) {
1342
- var req = this.reqs[id];
1343
- if (req) {
1344
- delete this.reqs[id];
1345
- clearTimeout (req.timer);
1346
- delete req.timer;
1347
- this.reqCount--;
1348
- if (this.reqCount <= 0)
1349
- this.dgram.unref();
1350
- return req;
1351
- } else {
1352
- return null;
1353
- }
1354
- };
1355
-
1356
- function walkCb (req, error, varbinds) {
1357
- var done = 0;
1358
- var oid;
1359
-
1360
- if (error) {
1361
- if (error instanceof RequestFailedError) {
1362
- if (error.status != ErrorStatus.NoSuchName) {
1363
- req.doneCb (error);
1364
- return;
1365
- } else {
1366
- // signal the version 1 walk code below that it should stop
1367
- done = 1;
1368
- }
1369
- } else {
1370
- req.doneCb (error);
1371
- return;
1372
- }
1373
- }
1374
-
1375
- if (this.version == Version2c) {
1376
- for (var i = varbinds[0].length; i > 0; i--) {
1377
- if (varbinds[0][i - 1].type == ObjectType.EndOfMibView) {
1378
- varbinds[0].pop ();
1379
- done = 1;
1380
- }
1381
- }
1382
- if (req.feedCb (varbinds[0]))
1383
- done = 1;
1384
- if (! done)
1385
- oid = varbinds[0][varbinds[0].length - 1].oid;
1386
- } else {
1387
- if (! done) {
1388
- if (req.feedCb (varbinds)) {
1389
- done = 1;
1390
- } else {
1391
- oid = varbinds[0].oid;
1392
- }
1393
- }
1394
- }
1395
-
1396
- if (done)
1397
- req.doneCb (null);
1398
- else
1399
- this.walk (oid, req.maxRepetitions, req.feedCb, req.doneCb,
1400
- req.baseOid);
1401
- }
1402
-
1403
- Session.prototype.walk = function () {
1404
- var me = this;
1405
- var oid = arguments[0];
1406
- var maxRepetitions, feedCb, doneCb, baseOid;
1407
-
1408
- if (arguments.length < 4) {
1409
- maxRepetitions = 20;
1410
- feedCb = arguments[1];
1411
- doneCb = arguments[2];
1412
- } else {
1413
- maxRepetitions = arguments[1];
1414
- feedCb = arguments[2];
1415
- doneCb = arguments[3];
1416
- }
1417
-
1418
- var req = {
1419
- maxRepetitions: maxRepetitions,
1420
- feedCb: feedCb,
1421
- doneCb: doneCb
1422
- };
1423
-
1424
- if (this.version == Version2c)
1425
- this.getBulk ([oid], 0, maxRepetitions,
1426
- walkCb.bind (me, req));
1427
- else
1428
- this.getNext ([oid], walkCb.bind (me, req));
1429
-
1430
- return this;
1431
- };
1432
-
1433
- /*****************************************************************************
1434
- ** Exports
1435
- **/
1436
-
1437
- exports.Session = Session;
1438
-
1439
- exports.createSession = function (target, community, options) {
1440
- return new Session (target, community, options);
1441
- };
1442
-
1443
- exports.isVarbindError = isVarbindError;
1444
- exports.varbindError = varbindError;
1445
-
1446
- exports.Version1 = Version1;
1447
- exports.Version2c = Version2c;
1448
-
1449
- exports.ErrorStatus = ErrorStatus;
1450
- exports.TrapType = TrapType;
1451
- exports.ObjectType = ObjectType;
1452
-
1453
- exports.ResponseInvalidError = ResponseInvalidError;
1454
- exports.RequestInvalidError = RequestInvalidError;
1455
- exports.RequestFailedError = RequestFailedError;
1456
- exports.RequestTimedOutError = RequestTimedOutError;
1457
-
1458
- /**
1459
- ** We've added this for testing.
1460
- **/
1461
- exports.ObjectParser = {
1462
- readInt: readInt,
1463
- readUint: readUint
1464
- };
1
+
2
+ // Copyright 2013 Stephen Vickers <stephen.vickers.sv@gmail.com>
3
+
4
+ var ber = require ("asn1-ber").Ber;
5
+ var dgram = require ("dgram");
6
+ var events = require ("events");
7
+ var util = require ("util");
8
+
9
+ /*****************************************************************************
10
+ ** Constants
11
+ **/
12
+
13
+ function _expandConstantObject (object) {
14
+ var keys = [];
15
+ for (var key in object)
16
+ keys.push (key);
17
+ for (var i = 0; i < keys.length; i++)
18
+ object[object[keys[i]]] = parseInt (keys[i]);
19
+ }
20
+
21
+ var ErrorStatus = {
22
+ 0: "NoError",
23
+ 1: "TooBig",
24
+ 2: "NoSuchName",
25
+ 3: "BadValue",
26
+ 4: "ReadOnly",
27
+ 5: "GeneralError",
28
+ 6: "NoAccess",
29
+ 7: "WrongType",
30
+ 8: "WrongLength",
31
+ 9: "WrongEncoding",
32
+ 10: "WrongValue",
33
+ 11: "NoCreation",
34
+ 12: "InconsistentValue",
35
+ 13: "ResourceUnavailable",
36
+ 14: "CommitFailed",
37
+ 15: "UndoFailed",
38
+ 16: "AuthorizationError",
39
+ 17: "NotWritable",
40
+ 18: "InconsistentName"
41
+ };
42
+
43
+ _expandConstantObject (ErrorStatus);
44
+
45
+ var ObjectType = {
46
+ 1: "Boolean",
47
+ 2: "Integer",
48
+ 4: "OctetString",
49
+ 5: "Null",
50
+ 6: "OID",
51
+ 64: "IpAddress",
52
+ 65: "Counter",
53
+ 66: "Gauge",
54
+ 67: "TimeTicks",
55
+ 68: "Opaque",
56
+ 70: "Counter64",
57
+ 128: "NoSuchObject",
58
+ 129: "NoSuchInstance",
59
+ 130: "EndOfMibView"
60
+ };
61
+
62
+ _expandConstantObject (ObjectType);
63
+
64
+ ObjectType.Integer32 = ObjectType.Integer;
65
+ ObjectType.Counter32 = ObjectType.Counter;
66
+ ObjectType.Gauge32 = ObjectType.Gauge;
67
+ ObjectType.Unsigned32 = ObjectType.Gauge32;
68
+
69
+ var PduType = {
70
+ 160: "GetRequest",
71
+ 161: "GetNextRequest",
72
+ 162: "GetResponse",
73
+ 163: "SetRequest",
74
+ 164: "Trap",
75
+ 165: "GetBulkRequest",
76
+ 166: "InformRequest",
77
+ 167: "TrapV2",
78
+ 168: "Report"
79
+ };
80
+
81
+ _expandConstantObject (PduType);
82
+
83
+ var TrapType = {
84
+ 0: "ColdStart",
85
+ 1: "WarmStart",
86
+ 2: "LinkDown",
87
+ 3: "LinkUp",
88
+ 4: "AuthenticationFailure",
89
+ 5: "EgpNeighborLoss",
90
+ 6: "EnterpriseSpecific"
91
+ };
92
+
93
+ _expandConstantObject (TrapType);
94
+
95
+ var Version1 = 0;
96
+ var Version2c = 1;
97
+
98
+ /*****************************************************************************
99
+ ** Exception class definitions
100
+ **/
101
+
102
+ function ResponseInvalidError (message) {
103
+ this.name = "ResponseInvalidError";
104
+ this.message = message;
105
+ Error.captureStackTrace(this, ResponseInvalidError);
106
+ }
107
+ util.inherits (ResponseInvalidError, Error);
108
+
109
+ function RequestInvalidError (message) {
110
+ this.name = "RequestInvalidError";
111
+ this.message = message;
112
+ Error.captureStackTrace(this, RequestInvalidError);
113
+ }
114
+ util.inherits (RequestInvalidError, Error);
115
+
116
+ function RequestFailedError (message, status) {
117
+ this.name = "RequestFailedError";
118
+ this.message = message;
119
+ this.status = status;
120
+ Error.captureStackTrace(this, RequestFailedError);
121
+ }
122
+ util.inherits (RequestFailedError, Error);
123
+
124
+ function RequestTimedOutError (message) {
125
+ this.name = "RequestTimedOutError";
126
+ this.message = message;
127
+ Error.captureStackTrace(this, RequestTimedOutError);
128
+ }
129
+ util.inherits (RequestTimedOutError, Error);
130
+
131
+ /*****************************************************************************
132
+ ** OID and varbind helper functions
133
+ **/
134
+
135
+ function isVarbindError (varbind) {
136
+ return !!(varbind.type == ObjectType.NoSuchObject
137
+ || varbind.type == ObjectType.NoSuchInstance
138
+ || varbind.type == ObjectType.EndOfMibView);
139
+ }
140
+
141
+ function varbindError (varbind) {
142
+ return (ObjectType[varbind.type] || "NotAnError") + ": " + varbind.oid;
143
+ }
144
+
145
+ function oidFollowsOid (oidString, nextString) {
146
+ var oid = {str: oidString, len: oidString.length, idx: 0};
147
+ var next = {str: nextString, len: nextString.length, idx: 0};
148
+ var dotCharCode = ".".charCodeAt (0);
149
+
150
+ function getNumber (item) {
151
+ var n = 0;
152
+ if (item.idx >= item.len)
153
+ return null;
154
+ while (item.idx < item.len) {
155
+ var charCode = item.str.charCodeAt (item.idx++);
156
+ if (charCode == dotCharCode)
157
+ return n;
158
+ n = (n ? (n * 10) : n) + (charCode - 48);
159
+ }
160
+ return n;
161
+ }
162
+
163
+ while (1) {
164
+ var oidNumber = getNumber (oid);
165
+ var nextNumber = getNumber (next);
166
+
167
+ if (oidNumber !== null) {
168
+ if (nextNumber !== null) {
169
+ if (nextNumber > oidNumber) {
170
+ return true;
171
+ } else if (nextNumber < oidNumber) {
172
+ return false;
173
+ }
174
+ } else {
175
+ return true;
176
+ }
177
+ } else {
178
+ return true;
179
+ }
180
+ }
181
+ }
182
+
183
+ function oidInSubtree (oidString, nextString) {
184
+ var oid = oidString.split (".");
185
+ var next = nextString.split (".");
186
+
187
+ if (oid.length > next.length)
188
+ return false;
189
+
190
+ for (var i = 0; i < oid.length; i++) {
191
+ if (next[i] != oid[i])
192
+ return false;
193
+ }
194
+
195
+ return true;
196
+ }
197
+
198
+ /**
199
+ ** Some SNMP agents produce integers on the wire such as 00 ff ff ff ff.
200
+ ** The ASN.1 BER parser we use throws an error when parsing this, which we
201
+ ** believe is correct. So, we decided not to bother the "asn1" developer(s)
202
+ ** with this, instead opting to work around it here.
203
+ **
204
+ ** If an integer is 5 bytes in length we check if the first byte is 0, and if so
205
+ ** simply drop it and parse it like it was a 4 byte integer, otherwise throw
206
+ ** an error since the integer is too large.
207
+ **/
208
+
209
+ function readInt (buffer) {
210
+ return readUint (buffer, true);
211
+ }
212
+
213
+ function readUint (buffer, isSigned) {
214
+ buffer.readByte ();
215
+ var length = buffer.readByte ();
216
+ var value = 0;
217
+ var signedBitSet = false;
218
+
219
+ if (length > 5) {
220
+ throw new RangeError ("Integer too long '" + length + "'");
221
+ } else if (length == 5) {
222
+ if (buffer.readByte () !== 0)
223
+ throw new RangeError ("Integer too long '" + length + "'");
224
+ length = 4;
225
+ }
226
+
227
+ for (var i = 0; i < length; i++) {
228
+ value *= 256;
229
+ value += buffer.readByte ();
230
+
231
+ if (isSigned && i <= 0) {
232
+ if ((value & 0x80) == 0x80)
233
+ signedBitSet = true;
234
+ }
235
+ }
236
+
237
+ if (signedBitSet)
238
+ value -= (1 << (i * 8));
239
+
240
+ return value;
241
+ }
242
+
243
+ function readUint64 (buffer) {
244
+ var value = buffer.readString (ObjectType.Counter64, true);
245
+
246
+ return value;
247
+ }
248
+
249
+ function readVarbinds (buffer, varbinds) {
250
+ buffer.readSequence ();
251
+
252
+ while (1) {
253
+ buffer.readSequence ();
254
+ var oid = buffer.readOID ();
255
+ var type = buffer.peek ();
256
+
257
+ if (type == null)
258
+ break;
259
+
260
+ var value;
261
+
262
+ if (type == ObjectType.Boolean) {
263
+ value = buffer.readBoolean ();
264
+ } else if (type == ObjectType.Integer) {
265
+ value = readInt (buffer);
266
+ } else if (type == ObjectType.OctetString) {
267
+ value = buffer.readString (null, true);
268
+ } else if (type == ObjectType.Null) {
269
+ buffer.readByte ();
270
+ buffer.readByte ();
271
+ value = null;
272
+ } else if (type == ObjectType.OID) {
273
+ value = buffer.readOID ();
274
+ } else if (type == ObjectType.IpAddress) {
275
+ var bytes = buffer.readString (ObjectType.IpAddress, true);
276
+ if (bytes.length != 4)
277
+ throw new ResponseInvalidError ("Length '" + bytes.length
278
+ + "' of IP address '" + bytes.toString ("hex")
279
+ + "' is not 4");
280
+ value = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
281
+ } else if (type == ObjectType.Counter) {
282
+ value = readUint (buffer);
283
+ } else if (type == ObjectType.Gauge) {
284
+ value = readUint (buffer);
285
+ } else if (type == ObjectType.TimeTicks) {
286
+ value = readUint (buffer);
287
+ } else if (type == ObjectType.Opaque) {
288
+ value = buffer.readString (ObjectType.Opaque, true);
289
+ } else if (type == ObjectType.Counter64) {
290
+ value = readUint64 (buffer);
291
+ } else if (type == ObjectType.NoSuchObject) {
292
+ buffer.readByte ();
293
+ buffer.readByte ();
294
+ value = null;
295
+ } else if (type == ObjectType.NoSuchInstance) {
296
+ buffer.readByte ();
297
+ buffer.readByte ();
298
+ value = null;
299
+ } else if (type == ObjectType.EndOfMibView) {
300
+ buffer.readByte ();
301
+ buffer.readByte ();
302
+ value = null;
303
+ } else {
304
+ throw new ResponseInvalidError ("Unknown type '" + type
305
+ + "' in response");
306
+ }
307
+
308
+ varbinds.push ({
309
+ oid: oid,
310
+ type: type,
311
+ value: value
312
+ });
313
+ }
314
+ }
315
+
316
+ function writeUint (buffer, type, value) {
317
+ var b = new Buffer (4);
318
+ b.writeUInt32BE (value, 0);
319
+ buffer.writeBuffer (b, type);
320
+ }
321
+
322
+ function writeUint64 (buffer, value) {
323
+ buffer.writeBuffer (value, ObjectType.Counter64);
324
+ }
325
+
326
+ function writeVarbinds (buffer, varbinds) {
327
+ buffer.startSequence ();
328
+ for (var i = 0; i < varbinds.length; i++) {
329
+ buffer.startSequence ();
330
+ buffer.writeOID (varbinds[i].oid);
331
+
332
+ if (varbinds[i].type && varbinds[i].hasOwnProperty("value")) {
333
+ var type = varbinds[i].type;
334
+ var value = varbinds[i].value;
335
+
336
+ if (type == ObjectType.Boolean) {
337
+ buffer.writeBoolean (value ? true : false);
338
+ } else if (type == ObjectType.Integer) { // also Integer32
339
+ buffer.writeInt (value);
340
+ } else if (type == ObjectType.OctetString) {
341
+ if (typeof value == "string")
342
+ buffer.writeString (value);
343
+ else
344
+ buffer.writeBuffer (value, ObjectType.OctetString);
345
+ } else if (type == ObjectType.Null) {
346
+ buffer.writeNull ();
347
+ } else if (type == ObjectType.OID) {
348
+ buffer.writeOID (value);
349
+ } else if (type == ObjectType.IpAddress) {
350
+ var bytes = value.split (".");
351
+ if (bytes.length != 4)
352
+ throw new RequestInvalidError ("Invalid IP address '"
353
+ + value + "'");
354
+ buffer.writeBuffer (new Buffer (bytes), 64);
355
+ } else if (type == ObjectType.Counter) { // also Counter32
356
+ writeUint (buffer, ObjectType.Counter, value);
357
+ } else if (type == ObjectType.Gauge) { // also Gauge32 & Unsigned32
358
+ writeUint (buffer, ObjectType.Gauge, value);
359
+ } else if (type == ObjectType.TimeTicks) {
360
+ writeUint (buffer, ObjectType.TimeTicks, value);
361
+ } else if (type == ObjectType.Opaque) {
362
+ buffer.writeBuffer (value, ObjectType.Opaque);
363
+ } else if (type == ObjectType.Counter64) {
364
+ writeUint64 (buffer, value);
365
+ } else {
366
+ throw new RequestInvalidError ("Unknown type '" + type
367
+ + "' in request");
368
+ }
369
+ } else {
370
+ buffer.writeNull ();
371
+ }
372
+
373
+ buffer.endSequence ();
374
+ }
375
+ buffer.endSequence ();
376
+ }
377
+
378
+ /*****************************************************************************
379
+ ** PDU class definitions
380
+ **/
381
+
382
+ var SimplePdu = function (id, varbinds, options) {
383
+ this.id = id;
384
+ this.varbinds = varbinds;
385
+ this.options = options || {};
386
+ };
387
+
388
+ SimplePdu.prototype.toBuffer = function (buffer) {
389
+ buffer.startSequence (this.type);
390
+
391
+ buffer.writeInt (this.id);
392
+ buffer.writeInt ((this.type == PduType.GetBulkRequest)
393
+ ? (this.options.nonRepeaters || 0)
394
+ : 0);
395
+ buffer.writeInt ((this.type == PduType.GetBulkRequest)
396
+ ? (this.options.maxRepetitions || 0)
397
+ : 0);
398
+
399
+ writeVarbinds (buffer, this.varbinds);
400
+
401
+ buffer.endSequence ();
402
+ };
403
+
404
+ var GetBulkRequestPdu = function () {
405
+ this.type = PduType.GetBulkRequest;
406
+ GetBulkRequestPdu.super_.apply (this, arguments);
407
+ };
408
+
409
+ util.inherits (GetBulkRequestPdu, SimplePdu);
410
+
411
+ var GetNextRequestPdu = function () {
412
+ this.type = PduType.GetNextRequest;
413
+ GetNextRequestPdu.super_.apply (this, arguments);
414
+ };
415
+
416
+ util.inherits (GetNextRequestPdu, SimplePdu);
417
+
418
+ var GetResponsePdu = function (buffer) {
419
+ this.type = PduType.GetResponse;
420
+
421
+ buffer.readSequence (this.type);
422
+
423
+ this.id = buffer.readInt ();
424
+
425
+ this.errorStatus = buffer.readInt ();
426
+ this.errorIndex = buffer.readInt ();
427
+
428
+ this.varbinds = [];
429
+
430
+ readVarbinds (buffer, this.varbinds);
431
+ };
432
+
433
+ var GetRequestPdu = function () {
434
+ this.type = PduType.GetRequest;
435
+ GetRequestPdu.super_.apply (this, arguments);
436
+ };
437
+
438
+ util.inherits (GetRequestPdu, SimplePdu);
439
+
440
+ var InformRequestPdu = function () {
441
+ this.type = PduType.InformRequest;
442
+ InformRequestPdu.super_.apply (this, arguments);
443
+ };
444
+
445
+ util.inherits (InformRequestPdu, SimplePdu);
446
+
447
+ var SetRequestPdu = function () {
448
+ this.type = PduType.SetRequest;
449
+ SetRequestPdu.super_.apply (this, arguments);
450
+ };
451
+
452
+ util.inherits (SetRequestPdu, SimplePdu);
453
+
454
+ var TrapPdu = function (typeOrOid, varbinds, options) {
455
+ this.type = PduType.Trap;
456
+
457
+ this.agentAddr = options.agentAddr || "127.0.0.1";
458
+ this.upTime = options.upTime;
459
+
460
+ if (typeof typeOrOid == "string") {
461
+ this.generic = TrapType.EnterpriseSpecific;
462
+ this.specific = parseInt (typeOrOid.match (/\.(\d+)$/)[1]);
463
+ this.enterprise = typeOrOid.replace (/\.(\d+)$/, "");
464
+ } else {
465
+ this.generic = typeOrOid;
466
+ this.specific = 0;
467
+ this.enterprise = "1.3.6.1.4.1";
468
+ }
469
+
470
+ this.varbinds = varbinds;
471
+ };
472
+
473
+ TrapPdu.prototype.toBuffer = function (buffer) {
474
+ buffer.startSequence (this.type);
475
+
476
+ buffer.writeOID (this.enterprise);
477
+ buffer.writeBuffer (new Buffer (this.agentAddr.split (".")),
478
+ ObjectType.IpAddress);
479
+ buffer.writeInt (this.generic);
480
+ buffer.writeInt (this.specific);
481
+ writeUint (buffer, ObjectType.TimeTicks,
482
+ this.upTime || Math.floor (process.uptime () * 100));
483
+
484
+ writeVarbinds (buffer, this.varbinds);
485
+
486
+ buffer.endSequence ();
487
+ };
488
+
489
+ var TrapV2Pdu = function () {
490
+ this.type = PduType.TrapV2;
491
+ TrapV2Pdu.super_.apply (this, arguments);
492
+ };
493
+
494
+ util.inherits (TrapV2Pdu, SimplePdu);
495
+
496
+ /*****************************************************************************
497
+ ** Message class definitions
498
+ **/
499
+
500
+ var RequestMessage = function (version, community, pdu) {
501
+ this.version = version;
502
+ this.community = community;
503
+ this.pdu = pdu;
504
+ };
505
+
506
+ RequestMessage.prototype.toBuffer = function () {
507
+ if (this.buffer)
508
+ return this.buffer;
509
+
510
+ var writer = new ber.Writer ();
511
+
512
+ writer.startSequence ();
513
+
514
+ writer.writeInt (this.version);
515
+ writer.writeString (this.community);
516
+
517
+ this.pdu.toBuffer (writer);
518
+
519
+ writer.endSequence ();
520
+
521
+ this.buffer = writer.buffer;
522
+
523
+ return this.buffer;
524
+ };
525
+
526
+ var ResponseMessage = function (buffer) {
527
+ var reader = new ber.Reader (buffer);
528
+
529
+ reader.readSequence ();
530
+
531
+ this.version = reader.readInt ();
532
+ this.community = reader.readString ();
533
+
534
+ var type = reader.peek ();
535
+
536
+ if (type == PduType.GetResponse) {
537
+ this.pdu = new GetResponsePdu (reader);
538
+ } else {
539
+ throw new ResponseInvalidError ("Unknown PDU type '" + type
540
+ + "' in response");
541
+ }
542
+ };
543
+
544
+ /*****************************************************************************
545
+ ** Session class definition
546
+ **/
547
+
548
+ var Session = function (target, community, options) {
549
+ this.target = target || "127.0.0.1";
550
+ this.community = community || "public";
551
+
552
+ this.version = (options && options.version)
553
+ ? options.version
554
+ : Version1;
555
+
556
+ this.transport = (options && options.transport)
557
+ ? options.transport
558
+ : "udp4";
559
+ this.port = (options && options.port )
560
+ ? options.port
561
+ : 161;
562
+ this.trapPort = (options && options.trapPort )
563
+ ? options.trapPort
564
+ : 162;
565
+
566
+ this.retries = (options && (options.retries || options.retries == 0))
567
+ ? options.retries
568
+ : 1;
569
+ this.timeout = (options && options.timeout)
570
+ ? options.timeout
571
+ : 5000;
572
+
573
+ this.sourceAddress = (options && options.sourceAddress )
574
+ ? options.sourceAddress
575
+ : undefined;
576
+ this.sourcePort = (options && options.sourcePort )
577
+ ? parseInt(options.sourcePort)
578
+ : undefined;
579
+
580
+ this.idBitsSize = (options && options.idBitsSize)
581
+ ? parseInt(options.idBitsSize)
582
+ : 32;
583
+
584
+ this.reqs = {};
585
+ this.reqCount = 0;
586
+
587
+ this.dgram = dgram.createSocket (this.transport);
588
+ this.dgram.unref();
589
+
590
+ var me = this;
591
+ this.dgram.on ("message", me.onMsg.bind (me));
592
+ this.dgram.on ("close", me.onClose.bind (me));
593
+ this.dgram.on ("error", me.onError.bind (me));
594
+
595
+ if (this.sourceAddress || this.sourcePort)
596
+ this.dgram.bind (this.sourcePort, this.sourceAddress);
597
+ };
598
+
599
+ util.inherits (Session, events.EventEmitter);
600
+
601
+ Session.prototype.close = function () {
602
+ this.dgram.close ();
603
+ return this;
604
+ };
605
+
606
+ Session.prototype.cancelRequests = function (error) {
607
+ var id;
608
+ for (id in this.reqs) {
609
+ var req = this.reqs[id];
610
+ this.unregisterRequest (req.id);
611
+ req.responseCb (error);
612
+ }
613
+ };
614
+
615
+ function _generateId (bitSize) {
616
+ if (bitSize === 16) {
617
+ return Math.floor(Math.random() * 10000) % 65535;
618
+ }
619
+ return Math.floor(Math.random() * 100000000) % 4294967295;
620
+ }
621
+
622
+ Session.prototype.get = function (oids, responseCb) {
623
+ function feedCb (req, message) {
624
+ var pdu = message.pdu;
625
+ var varbinds = [];
626
+
627
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
628
+ req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
629
+ + "match response OIDs"));
630
+ } else {
631
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
632
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
633
+ req.responseCb (new ResponseInvalidError ("OID '"
634
+ + req.message.pdu.varbinds[i].oid
635
+ + "' in request at positiion '" + i + "' does not "
636
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
637
+ + "at position '" + i + "'"));
638
+ return;
639
+ } else {
640
+ varbinds.push (pdu.varbinds[i]);
641
+ }
642
+ }
643
+
644
+ req.responseCb (null, varbinds);
645
+ }
646
+ }
647
+
648
+ var pduVarbinds = [];
649
+
650
+ for (var i = 0; i < oids.length; i++) {
651
+ var varbind = {
652
+ oid: oids[i]
653
+ };
654
+ pduVarbinds.push (varbind);
655
+ }
656
+
657
+ this.simpleGet (GetRequestPdu, feedCb, pduVarbinds, responseCb);
658
+
659
+ return this;
660
+ };
661
+
662
+ Session.prototype.getBulk = function () {
663
+ var oids, nonRepeaters, maxRepetitions, responseCb;
664
+
665
+ if (arguments.length >= 4) {
666
+ oids = arguments[0];
667
+ nonRepeaters = arguments[1];
668
+ maxRepetitions = arguments[2];
669
+ responseCb = arguments[3];
670
+ } else if (arguments.length >= 3) {
671
+ oids = arguments[0];
672
+ nonRepeaters = arguments[1];
673
+ maxRepetitions = 10;
674
+ responseCb = arguments[2];
675
+ } else {
676
+ oids = arguments[0];
677
+ nonRepeaters = 0;
678
+ maxRepetitions = 10;
679
+ responseCb = arguments[1];
680
+ }
681
+
682
+ function feedCb (req, message) {
683
+ var pdu = message.pdu;
684
+ var varbinds = [];
685
+ var i = 0;
686
+
687
+ // first walk through and grab non-repeaters
688
+ if (pdu.varbinds.length < nonRepeaters) {
689
+ req.responseCb (new ResponseInvalidError ("Varbind count in "
690
+ + "response '" + pdu.varbinds.length + "' is less than "
691
+ + "non-repeaters '" + nonRepeaters + "' in request"));
692
+ } else {
693
+ for ( ; i < nonRepeaters; i++) {
694
+ if (isVarbindError (pdu.varbinds[i])) {
695
+ varbinds.push (pdu.varbinds[i]);
696
+ } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
697
+ pdu.varbinds[i].oid)) {
698
+ req.responseCb (new ResponseInvalidError ("OID '"
699
+ + req.message.pdu.varbinds[i].oid + "' in request at "
700
+ + "positiion '" + i + "' does not precede "
701
+ + "OID '" + pdu.varbinds[i].oid + "' in response "
702
+ + "at position '" + i + "'"));
703
+ return;
704
+ } else {
705
+ varbinds.push (pdu.varbinds[i]);
706
+ }
707
+ }
708
+ }
709
+
710
+ var repeaters = req.message.pdu.varbinds.length - nonRepeaters;
711
+
712
+ // secondly walk through and grab repeaters
713
+ if (pdu.varbinds.length % (repeaters)) {
714
+ req.responseCb (new ResponseInvalidError ("Varbind count in "
715
+ + "response '" + pdu.varbinds.length + "' is not a "
716
+ + "multiple of repeaters '" + repeaters
717
+ + "' plus non-repeaters '" + nonRepeaters + "' in request"));
718
+ } else {
719
+ while (i < pdu.varbinds.length) {
720
+ for (var j = 0; j < repeaters; j++, i++) {
721
+ var reqIndex = nonRepeaters + j;
722
+ var respIndex = i;
723
+
724
+ if (isVarbindError (pdu.varbinds[respIndex])) {
725
+ if (! varbinds[reqIndex])
726
+ varbinds[reqIndex] = [];
727
+ varbinds[reqIndex].push (pdu.varbinds[respIndex]);
728
+ } else if (! oidFollowsOid (
729
+ req.message.pdu.varbinds[reqIndex].oid,
730
+ pdu.varbinds[respIndex].oid)) {
731
+ req.responseCb (new ResponseInvalidError ("OID '"
732
+ + req.message.pdu.varbinds[reqIndex].oid
733
+ + "' in request at positiion '" + (reqIndex)
734
+ + "' does not precede OID '"
735
+ + pdu.varbinds[respIndex].oid
736
+ + "' in response at position '" + (respIndex) + "'"));
737
+ return;
738
+ } else {
739
+ if (! varbinds[reqIndex])
740
+ varbinds[reqIndex] = [];
741
+ varbinds[reqIndex].push (pdu.varbinds[respIndex]);
742
+ }
743
+ }
744
+ }
745
+ }
746
+
747
+ req.responseCb (null, varbinds);
748
+ }
749
+
750
+ var pduVarbinds = [];
751
+
752
+ for (var i = 0; i < oids.length; i++) {
753
+ var varbind = {
754
+ oid: oids[i]
755
+ };
756
+ pduVarbinds.push (varbind);
757
+ }
758
+
759
+ var options = {
760
+ nonRepeaters: nonRepeaters,
761
+ maxRepetitions: maxRepetitions
762
+ };
763
+
764
+ this.simpleGet (GetBulkRequestPdu, feedCb, pduVarbinds, responseCb,
765
+ options);
766
+
767
+ return this;
768
+ };
769
+
770
+ Session.prototype.getNext = function (oids, responseCb) {
771
+ function feedCb (req, message) {
772
+ var pdu = message.pdu;
773
+ var varbinds = [];
774
+
775
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
776
+ req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
777
+ + "match response OIDs"));
778
+ } else {
779
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
780
+ if (isVarbindError (pdu.varbinds[i])) {
781
+ varbinds.push (pdu.varbinds[i]);
782
+ } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
783
+ pdu.varbinds[i].oid)) {
784
+ req.responseCb (new ResponseInvalidError ("OID '"
785
+ + req.message.pdu.varbinds[i].oid + "' in request at "
786
+ + "positiion '" + i + "' does not precede "
787
+ + "OID '" + pdu.varbinds[i].oid + "' in response "
788
+ + "at position '" + i + "'"));
789
+ return;
790
+ } else {
791
+ varbinds.push (pdu.varbinds[i]);
792
+ }
793
+ }
794
+
795
+ req.responseCb (null, varbinds);
796
+ }
797
+ }
798
+
799
+ var pduVarbinds = [];
800
+
801
+ for (var i = 0; i < oids.length; i++) {
802
+ var varbind = {
803
+ oid: oids[i]
804
+ };
805
+ pduVarbinds.push (varbind);
806
+ }
807
+
808
+ this.simpleGet (GetNextRequestPdu, feedCb, pduVarbinds, responseCb);
809
+
810
+ return this;
811
+ };
812
+
813
+ Session.prototype.inform = function () {
814
+ var typeOrOid = arguments[0];
815
+ var varbinds, options = {}, responseCb;
816
+
817
+ /**
818
+ ** Support the following signatures:
819
+ **
820
+ ** typeOrOid, varbinds, options, callback
821
+ ** typeOrOid, varbinds, callback
822
+ ** typeOrOid, options, callback
823
+ ** typeOrOid, callback
824
+ **/
825
+ if (arguments.length >= 4) {
826
+ varbinds = arguments[1];
827
+ options = arguments[2];
828
+ responseCb = arguments[3];
829
+ } else if (arguments.length >= 3) {
830
+ if (arguments[1].constructor != Array) {
831
+ varbinds = [];
832
+ options = arguments[1];
833
+ responseCb = arguments[2];
834
+ } else {
835
+ varbinds = arguments[1];
836
+ responseCb = arguments[2];
837
+ }
838
+ } else {
839
+ varbinds = [];
840
+ responseCb = arguments[1];
841
+ }
842
+
843
+ function feedCb (req, message) {
844
+ var pdu = message.pdu;
845
+ var varbinds = [];
846
+
847
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
848
+ req.responseCb (new ResponseInvalidError ("Inform OIDs do not "
849
+ + "match response OIDs"));
850
+ } else {
851
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
852
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
853
+ req.responseCb (new ResponseInvalidError ("OID '"
854
+ + req.message.pdu.varbinds[i].oid
855
+ + "' in inform at positiion '" + i + "' does not "
856
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
857
+ + "at position '" + i + "'"));
858
+ return;
859
+ } else {
860
+ varbinds.push (pdu.varbinds[i]);
861
+ }
862
+ }
863
+
864
+ req.responseCb (null, varbinds);
865
+ }
866
+ }
867
+
868
+ if (typeof typeOrOid != "string")
869
+ typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
870
+
871
+ var pduVarbinds = [
872
+ {
873
+ oid: "1.3.6.1.2.1.1.3.0",
874
+ type: ObjectType.TimeTicks,
875
+ value: options.upTime || Math.floor (process.uptime () * 100)
876
+ },
877
+ {
878
+ oid: "1.3.6.1.6.3.1.1.4.1.0",
879
+ type: ObjectType.OID,
880
+ value: typeOrOid
881
+ }
882
+ ];
883
+
884
+ for (var i = 0; i < varbinds.length; i++) {
885
+ var varbind = {
886
+ oid: varbinds[i].oid,
887
+ type: varbinds[i].type,
888
+ value: varbinds[i].value
889
+ };
890
+ pduVarbinds.push (varbind);
891
+ }
892
+
893
+ options.port = this.trapPort;
894
+
895
+ this.simpleGet (InformRequestPdu, feedCb, pduVarbinds, responseCb, options);
896
+
897
+ return this;
898
+ };
899
+
900
+ Session.prototype.onClose = function () {
901
+ this.cancelRequests (new Error ("Socket forcibly closed"));
902
+ this.emit ("close");
903
+ };
904
+
905
+ Session.prototype.onError = function (error) {
906
+ this.emit (error);
907
+ };
908
+
909
+ Session.prototype.onMsg = function (buffer, remote) {
910
+ try {
911
+ var message = new ResponseMessage (buffer);
912
+
913
+ var req = this.unregisterRequest (message.pdu.id);
914
+ if (! req)
915
+ return;
916
+
917
+ try {
918
+ if (message.version != req.message.version) {
919
+ req.responseCb (new ResponseInvalidError ("Version in request '"
920
+ + req.message.version + "' does not match version in "
921
+ + "response '" + message.version));
922
+ } else if (message.community != req.message.community) {
923
+ req.responseCb (new ResponseInvalidError ("Community '"
924
+ + req.message.community + "' in request does not match "
925
+ + "community '" + message.community + "' in response"));
926
+ } else if (message.pdu.type == PduType.GetResponse) {
927
+ req.onResponse (req, message);
928
+ } else {
929
+ req.responseCb (new ResponseInvalidError ("Unknown PDU type '"
930
+ + message.pdu.type + "' in response"));
931
+ }
932
+ } catch (error) {
933
+ req.responseCb (error);
934
+ }
935
+ } catch (error) {
936
+ this.emit("error", error);
937
+ }
938
+ };
939
+
940
+ Session.prototype.onSimpleGetResponse = function (req, message) {
941
+ var pdu = message.pdu;
942
+
943
+ if (pdu.errorStatus > 0) {
944
+ var statusString = ErrorStatus[pdu.errorStatus]
945
+ || ErrorStatus.GeneralError;
946
+ var statusCode = ErrorStatus[statusString]
947
+ || ErrorStatus[ErrorStatus.GeneralError];
948
+
949
+ if (pdu.errorIndex <= 0 || pdu.errorIndex > pdu.varbinds.length) {
950
+ req.responseCb (new RequestFailedError (statusString, statusCode));
951
+ } else {
952
+ var oid = pdu.varbinds[pdu.errorIndex - 1].oid;
953
+ var error = new RequestFailedError (statusString + ": " + oid,
954
+ statusCode);
955
+ req.responseCb (error);
956
+ }
957
+ } else {
958
+ req.feedCb (req, message);
959
+ }
960
+ };
961
+
962
+ Session.prototype.registerRequest = function (req) {
963
+ if (! this.reqs[req.id]) {
964
+ this.reqs[req.id] = req;
965
+ if (this.reqCount <= 0)
966
+ this.dgram.ref();
967
+ this.reqCount++;
968
+ }
969
+ var me = this;
970
+ req.timer = setTimeout (function () {
971
+ if (req.retries-- > 0) {
972
+ me.send (req);
973
+ } else {
974
+ me.unregisterRequest (req.id);
975
+ req.responseCb (new RequestTimedOutError (
976
+ "Request timed out"));
977
+ }
978
+ }, req.timeout);
979
+ };
980
+
981
+ Session.prototype.send = function (req, noWait) {
982
+ try {
983
+ var me = this;
984
+
985
+ var buffer = req.message.toBuffer ();
986
+
987
+ this.dgram.send (buffer, 0, buffer.length, req.port, this.target,
988
+ function (error, bytes) {
989
+ if (error) {
990
+ req.responseCb (error);
991
+ } else {
992
+ if (noWait) {
993
+ req.responseCb (null);
994
+ } else {
995
+ me.registerRequest (req);
996
+ }
997
+ }
998
+ });
999
+ } catch (error) {
1000
+ req.responseCb (error);
1001
+ }
1002
+
1003
+ return this;
1004
+ };
1005
+
1006
+ Session.prototype.set = function (varbinds, responseCb) {
1007
+ function feedCb (req, message) {
1008
+ var pdu = message.pdu;
1009
+ var varbinds = [];
1010
+
1011
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1012
+ req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
1013
+ + "match response OIDs"));
1014
+ } else {
1015
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1016
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1017
+ req.responseCb (new ResponseInvalidError ("OID '"
1018
+ + req.message.pdu.varbinds[i].oid
1019
+ + "' in request at positiion '" + i + "' does not "
1020
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
1021
+ + "at position '" + i + "'"));
1022
+ return;
1023
+ } else {
1024
+ varbinds.push (pdu.varbinds[i]);
1025
+ }
1026
+ }
1027
+
1028
+ req.responseCb (null, varbinds);
1029
+ }
1030
+ }
1031
+
1032
+ var pduVarbinds = [];
1033
+
1034
+ for (var i = 0; i < varbinds.length; i++) {
1035
+ var varbind = {
1036
+ oid: varbinds[i].oid,
1037
+ type: varbinds[i].type,
1038
+ value: varbinds[i].value
1039
+ };
1040
+ pduVarbinds.push (varbind);
1041
+ }
1042
+
1043
+ this.simpleGet (SetRequestPdu, feedCb, pduVarbinds, responseCb);
1044
+
1045
+ return this;
1046
+ };
1047
+
1048
+ Session.prototype.simpleGet = function (pduClass, feedCb, varbinds,
1049
+ responseCb, options) {
1050
+ var req = {};
1051
+
1052
+ try {
1053
+ var id = _generateId (this.idBitsSize);
1054
+ var pdu = new pduClass (id, varbinds, options);
1055
+ var message = new RequestMessage (this.version, this.community, pdu);
1056
+
1057
+ req = {
1058
+ id: id,
1059
+ message: message,
1060
+ responseCb: responseCb,
1061
+ retries: this.retries,
1062
+ timeout: this.timeout,
1063
+ onResponse: this.onSimpleGetResponse,
1064
+ feedCb: feedCb,
1065
+ port: (options && options.port) ? options.port : this.port
1066
+ };
1067
+
1068
+ this.send (req);
1069
+ } catch (error) {
1070
+ if (req.responseCb)
1071
+ req.responseCb (error);
1072
+ }
1073
+ };
1074
+
1075
+ function subtreeCb (req, varbinds) {
1076
+ var done = 0;
1077
+
1078
+ for (var i = varbinds.length; i > 0; i--) {
1079
+ if (! oidInSubtree (req.baseOid, varbinds[i - 1].oid)) {
1080
+ done = 1;
1081
+ varbinds.pop ();
1082
+ }
1083
+ }
1084
+
1085
+ if (varbinds.length > 0)
1086
+ req.feedCb (varbinds);
1087
+
1088
+ if (done)
1089
+ return true;
1090
+ }
1091
+
1092
+ Session.prototype.subtree = function () {
1093
+ var me = this;
1094
+ var oid = arguments[0];
1095
+ var maxRepetitions, feedCb, doneCb;
1096
+
1097
+ if (arguments.length < 4) {
1098
+ maxRepetitions = 20;
1099
+ feedCb = arguments[1];
1100
+ doneCb = arguments[2];
1101
+ } else {
1102
+ maxRepetitions = arguments[1];
1103
+ feedCb = arguments[2];
1104
+ doneCb = arguments[3];
1105
+ }
1106
+
1107
+ var req = {
1108
+ feedCb: feedCb,
1109
+ doneCb: doneCb,
1110
+ maxRepetitions: maxRepetitions,
1111
+ baseOid: oid
1112
+ };
1113
+
1114
+ this.walk (oid, maxRepetitions, subtreeCb.bind (me, req), doneCb);
1115
+
1116
+ return this;
1117
+ };
1118
+
1119
+ function tableColumnsResponseCb (req, error) {
1120
+ if (error) {
1121
+ req.responseCb (error);
1122
+ } else if (req.error) {
1123
+ req.responseCb (req.error);
1124
+ } else {
1125
+ if (req.columns.length > 0) {
1126
+ var column = req.columns.pop ();
1127
+ var me = this;
1128
+ this.subtree (req.rowOid + column, req.maxRepetitions,
1129
+ tableColumnsFeedCb.bind (me, req),
1130
+ tableColumnsResponseCb.bind (me, req));
1131
+ } else {
1132
+ req.responseCb (null, req.table);
1133
+ }
1134
+ }
1135
+ }
1136
+
1137
+ function tableColumnsFeedCb (req, varbinds) {
1138
+ for (var i = 0; i < varbinds.length; i++) {
1139
+ if (isVarbindError (varbinds[i])) {
1140
+ req.error = new RequestFailedError (varbindError (varbind[i]));
1141
+ return true;
1142
+ }
1143
+
1144
+ var oid = varbinds[i].oid.replace (req.rowOid, "");
1145
+ if (oid && oid != varbinds[i].oid) {
1146
+ var match = oid.match (/^(\d+)\.(.+)$/);
1147
+ if (match && match[1] > 0) {
1148
+ if (! req.table[match[2]])
1149
+ req.table[match[2]] = {};
1150
+ req.table[match[2]][match[1]] = varbinds[i].value;
1151
+ }
1152
+ }
1153
+ }
1154
+ }
1155
+
1156
+ Session.prototype.tableColumns = function () {
1157
+ var me = this;
1158
+
1159
+ var oid = arguments[0];
1160
+ var columns = arguments[1];
1161
+ var maxRepetitions, responseCb;
1162
+
1163
+ if (arguments.length < 4) {
1164
+ responseCb = arguments[2];
1165
+ maxRepetitions = 20;
1166
+ } else {
1167
+ maxRepetitions = arguments[2];
1168
+ responseCb = arguments[3];
1169
+ }
1170
+
1171
+ var req = {
1172
+ responseCb: responseCb,
1173
+ maxRepetitions: maxRepetitions,
1174
+ baseOid: oid,
1175
+ rowOid: oid + ".1.",
1176
+ columns: columns.slice(0),
1177
+ table: {}
1178
+ };
1179
+
1180
+ if (req.columns.length > 0) {
1181
+ var column = req.columns.pop ();
1182
+ this.subtree (req.rowOid + column, maxRepetitions,
1183
+ tableColumnsFeedCb.bind (me, req),
1184
+ tableColumnsResponseCb.bind (me, req));
1185
+ }
1186
+
1187
+ return this;
1188
+ };
1189
+
1190
+ function tableResponseCb (req, error) {
1191
+ if (error)
1192
+ req.responseCb (error);
1193
+ else if (req.error)
1194
+ req.responseCb (req.error);
1195
+ else
1196
+ req.responseCb (null, req.table);
1197
+ }
1198
+
1199
+ function tableFeedCb (req, varbinds) {
1200
+ for (var i = 0; i < varbinds.length; i++) {
1201
+ if (isVarbindError (varbinds[i])) {
1202
+ req.error = new RequestFailedError (varbindError (varbind[i]));
1203
+ return true;
1204
+ }
1205
+
1206
+ var oid = varbinds[i].oid.replace (req.rowOid, "");
1207
+ if (oid && oid != varbinds[i].oid) {
1208
+ var match = oid.match (/^(\d+)\.(.+)$/);
1209
+ if (match && match[1] > 0) {
1210
+ if (! req.table[match[2]])
1211
+ req.table[match[2]] = {};
1212
+ req.table[match[2]][match[1]] = varbinds[i].value;
1213
+ }
1214
+ }
1215
+ }
1216
+ }
1217
+
1218
+ Session.prototype.table = function () {
1219
+ var me = this;
1220
+
1221
+ var oid = arguments[0];
1222
+ var maxRepetitions, responseCb;
1223
+
1224
+ if (arguments.length < 3) {
1225
+ responseCb = arguments[1];
1226
+ maxRepetitions = 20;
1227
+ } else {
1228
+ maxRepetitions = arguments[1];
1229
+ responseCb = arguments[2];
1230
+ }
1231
+
1232
+ var req = {
1233
+ responseCb: responseCb,
1234
+ maxRepetitions: maxRepetitions,
1235
+ baseOid: oid,
1236
+ rowOid: oid + ".1.",
1237
+ table: {}
1238
+ };
1239
+
1240
+ this.subtree (oid, maxRepetitions, tableFeedCb.bind (me, req),
1241
+ tableResponseCb.bind (me, req));
1242
+
1243
+ return this;
1244
+ };
1245
+
1246
+ Session.prototype.trap = function () {
1247
+ var req = {};
1248
+
1249
+ try {
1250
+ var typeOrOid = arguments[0];
1251
+ var varbinds, options = {}, responseCb;
1252
+
1253
+ /**
1254
+ ** Support the following signatures:
1255
+ **
1256
+ ** typeOrOid, varbinds, options, callback
1257
+ ** typeOrOid, varbinds, agentAddr, callback
1258
+ ** typeOrOid, varbinds, callback
1259
+ ** typeOrOid, agentAddr, callback
1260
+ ** typeOrOid, options, callback
1261
+ ** typeOrOid, callback
1262
+ **/
1263
+ if (arguments.length >= 4) {
1264
+ varbinds = arguments[1];
1265
+ if (typeof arguments[2] == "string") {
1266
+ options.agentAddr = arguments[2];
1267
+ } else if (arguments[2].constructor != Array) {
1268
+ options = arguments[2];
1269
+ }
1270
+ responseCb = arguments[3];
1271
+ } else if (arguments.length >= 3) {
1272
+ if (typeof arguments[1] == "string") {
1273
+ varbinds = [];
1274
+ options.agentAddr = arguments[1];
1275
+ } else if (arguments[1].constructor != Array) {
1276
+ varbinds = [];
1277
+ options = arguments[1];
1278
+ } else {
1279
+ varbinds = arguments[1];
1280
+ agentAddr = null;
1281
+ }
1282
+ responseCb = arguments[2];
1283
+ } else {
1284
+ varbinds = [];
1285
+ responseCb = arguments[1];
1286
+ }
1287
+
1288
+ var pdu, pduVarbinds = [];
1289
+
1290
+ for (var i = 0; i < varbinds.length; i++) {
1291
+ var varbind = {
1292
+ oid: varbinds[i].oid,
1293
+ type: varbinds[i].type,
1294
+ value: varbinds[i].value
1295
+ };
1296
+ pduVarbinds.push (varbind);
1297
+ }
1298
+
1299
+ var id = _generateId (this.idBitsSize);
1300
+
1301
+ if (this.version == Version2c) {
1302
+ if (typeof typeOrOid != "string")
1303
+ typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
1304
+
1305
+ pduVarbinds.unshift (
1306
+ {
1307
+ oid: "1.3.6.1.2.1.1.3.0",
1308
+ type: ObjectType.TimeTicks,
1309
+ value: options.upTime || Math.floor (process.uptime () * 100)
1310
+ },
1311
+ {
1312
+ oid: "1.3.6.1.6.3.1.1.4.1.0",
1313
+ type: ObjectType.OID,
1314
+ value: typeOrOid
1315
+ }
1316
+ );
1317
+
1318
+ pdu = new TrapV2Pdu (id, pduVarbinds, options);
1319
+ } else {
1320
+ pdu = new TrapPdu (typeOrOid, pduVarbinds, options);
1321
+ }
1322
+
1323
+ var message = new RequestMessage (this.version, this.community, pdu);
1324
+
1325
+ req = {
1326
+ id: id,
1327
+ message: message,
1328
+ responseCb: responseCb,
1329
+ port: this.trapPort
1330
+ };
1331
+
1332
+ this.send (req, true);
1333
+ } catch (error) {
1334
+ if (req.responseCb)
1335
+ req.responseCb (error);
1336
+ }
1337
+
1338
+ return this;
1339
+ };
1340
+
1341
+ Session.prototype.unregisterRequest = function (id) {
1342
+ var req = this.reqs[id];
1343
+ if (req) {
1344
+ delete this.reqs[id];
1345
+ clearTimeout (req.timer);
1346
+ delete req.timer;
1347
+ this.reqCount--;
1348
+ if (this.reqCount <= 0)
1349
+ this.dgram.unref();
1350
+ return req;
1351
+ } else {
1352
+ return null;
1353
+ }
1354
+ };
1355
+
1356
+ function walkCb (req, error, varbinds) {
1357
+ var done = 0;
1358
+ var oid;
1359
+
1360
+ if (error) {
1361
+ if (error instanceof RequestFailedError) {
1362
+ if (error.status != ErrorStatus.NoSuchName) {
1363
+ req.doneCb (error);
1364
+ return;
1365
+ } else {
1366
+ // signal the version 1 walk code below that it should stop
1367
+ done = 1;
1368
+ }
1369
+ } else {
1370
+ req.doneCb (error);
1371
+ return;
1372
+ }
1373
+ }
1374
+
1375
+ if (this.version == Version2c) {
1376
+ for (var i = varbinds[0].length; i > 0; i--) {
1377
+ if (varbinds[0][i - 1].type == ObjectType.EndOfMibView) {
1378
+ varbinds[0].pop ();
1379
+ done = 1;
1380
+ }
1381
+ }
1382
+ if (req.feedCb (varbinds[0]))
1383
+ done = 1;
1384
+ if (! done)
1385
+ oid = varbinds[0][varbinds[0].length - 1].oid;
1386
+ } else {
1387
+ if (! done) {
1388
+ if (req.feedCb (varbinds)) {
1389
+ done = 1;
1390
+ } else {
1391
+ oid = varbinds[0].oid;
1392
+ }
1393
+ }
1394
+ }
1395
+
1396
+ if (done)
1397
+ req.doneCb (null);
1398
+ else
1399
+ this.walk (oid, req.maxRepetitions, req.feedCb, req.doneCb,
1400
+ req.baseOid);
1401
+ }
1402
+
1403
+ Session.prototype.walk = function () {
1404
+ var me = this;
1405
+ var oid = arguments[0];
1406
+ var maxRepetitions, feedCb, doneCb, baseOid;
1407
+
1408
+ if (arguments.length < 4) {
1409
+ maxRepetitions = 20;
1410
+ feedCb = arguments[1];
1411
+ doneCb = arguments[2];
1412
+ } else {
1413
+ maxRepetitions = arguments[1];
1414
+ feedCb = arguments[2];
1415
+ doneCb = arguments[3];
1416
+ }
1417
+
1418
+ var req = {
1419
+ maxRepetitions: maxRepetitions,
1420
+ feedCb: feedCb,
1421
+ doneCb: doneCb
1422
+ };
1423
+
1424
+ if (this.version == Version2c)
1425
+ this.getBulk ([oid], 0, maxRepetitions,
1426
+ walkCb.bind (me, req));
1427
+ else
1428
+ this.getNext ([oid], walkCb.bind (me, req));
1429
+
1430
+ return this;
1431
+ };
1432
+
1433
+ /*****************************************************************************
1434
+ ** Exports
1435
+ **/
1436
+
1437
+ exports.Session = Session;
1438
+
1439
+ exports.createSession = function (target, community, options) {
1440
+ return new Session (target, community, options);
1441
+ };
1442
+
1443
+ exports.isVarbindError = isVarbindError;
1444
+ exports.varbindError = varbindError;
1445
+
1446
+ exports.Version1 = Version1;
1447
+ exports.Version2c = Version2c;
1448
+
1449
+ exports.ErrorStatus = ErrorStatus;
1450
+ exports.TrapType = TrapType;
1451
+ exports.ObjectType = ObjectType;
1452
+
1453
+ exports.ResponseInvalidError = ResponseInvalidError;
1454
+ exports.RequestInvalidError = RequestInvalidError;
1455
+ exports.RequestFailedError = RequestFailedError;
1456
+ exports.RequestTimedOutError = RequestTimedOutError;
1457
+
1458
+ /**
1459
+ ** We've added this for testing.
1460
+ **/
1461
+ exports.ObjectParser = {
1462
+ readInt: readInt,
1463
+ readUint: readUint
1464
+ };