added SNMP node.js data collector; node.d.plugin now supports multiple processors (http, snmp at the ones currently implemented)
Costa Tsaousis (ktsaou) committed
Feb 5, 2016 at 02:02 UTC
cac53fd155c250599871b12ebc1e7f83e1616777
14 files changed
+2624
-104
LICENSE.md
+23
@@ -114,4 +114,27 @@ connectivity is not available.
114
Copyright 2015, Mike Bostock
115
[BSD License](http://opensource.org/licenses/BSD-3-Clause)
116
117
+
118
+- [node-extend](https://github.com/justmoon/node-extend)
119
+
120
+ Copyright 2014, Stefan Thomas
121
+ [MIT License](https://github.com/justmoon/node-extend/blob/master/LICENSE)
122
+
123
+
124
+- [node-net-snmp](https://github.com/stephenwvickers/node-net-snmp)
125
+
126
+ Copyright 2013, Stephen Vickers
127
+ [MIT License](https://github.com/stephenwvickers/node-net-snmp)
128
+
129
130
+- [node-asn1](https://github.com/mcavage/node-asn1)
131
+
132
+ Copyright 2011, Mark Cavage
133
+ [MIT License](https://github.com/mcavage/node-asn1)
134
+
135
+
136
+- [pixl-xml](https://github.com/jhuckaby/pixl-xml)
137
+
138
+ Copyright 2015, Joseph Huckaby
139
+ [MIT License](https://github.com/jhuckaby/pixl-xml)
140
+
node.d/Makefile.am
+12
@@ -4,6 +4,7 @@ dist_node_SCRIPTS = \
4
README.md \
5
named.node.js \
6
sma_webbox.node.js \
7
+ snmp.node.js \
8
$(NULL)
9
10
nodemodulesdir=$(nodedir)/node_modules
@@ -11,4 +12,15 @@ dist_nodemodules_DATA = \
12
node_modules/netdata.js \
13
node_modules/extend.js \
14
node_modules/pixl-xml.js \
15
+ node_modules/net-snmp.js \
16
+ node_modules/asn1.js \
17
+ $(NULL)
18
+
19
+nodemodulesberdir=$(nodedir)/node_modules/ber
20
+dist_nodemodulesber_DATA = \
21
+ node_modules/ber/index.js \
22
+ node_modules/ber/errors.js \
23
+ node_modules/ber/reader.js \
24
+ node_modules/ber/types.js \
25
+ node_modules/ber/writer.js \
26
$(NULL)
node.d/named.node.js
+5
-7
@@ -46,7 +46,7 @@ if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plug
46
var named = {
47
name: __filename,
48
enable_autodetect: true,
49
- update_every: 1000,
49
+ update_every: 1,
50
51
charts: {},
52
@@ -60,7 +60,7 @@ var named = {
60
category: category_prefix + '_' + service.name, // the category of the chart
61
type: type, // the type of the chart
62
priority: priority, // the priority relative to others in the same family and category
63
- update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
63
+ update_every: service.update_every, // the expected update frequency of the chart
64
dimensions: {}
65
}
66
@@ -338,7 +338,7 @@ var named = {
338
category: 'named', // the category of the chart
339
type: netdata.chartTypes.line, // the type of the chart
340
priority: 150, // the priority relative to others in the same family and category
341
- update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
341
+ update_every: service.update_every, // the expected update frequency of the chart
342
dimensions: {
343
'clients': {
344
id: 'clients', // the unique id of the dimension
@@ -442,7 +442,7 @@ var named = {
442
category: 'named', // the category of the chart
443
type: netdata.chartTypes.line, // the type of the chart
444
priority: 5000, // the priority relative to others in the same family and category
445
- update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
445
+ update_every: service.update_every, // the expected update frequency of the chart
446
dimensions: {
447
'queries': {
448
id: 'queries', // the unique id of the dimension
@@ -486,7 +486,7 @@ var named = {
486
category: 'named', // the category of the chart
487
type: netdata.chartTypes.area, // the type of the chart
488
priority: 8000, // the priority relative to others in the same family and category
489
- update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
489
+ update_every: service.update_every, // the expected update frequency of the chart
490
dimensions: {
491
'CacheHits': {
492
id: 'CacheHits', // the unique id of the dimension
@@ -563,8 +563,6 @@ var named = {
563
while(len--) {
564
if(typeof config.servers[len].update_every === 'undefined')
565
config.servers[len].update_every = this.update_every;
566
- else
567
- config.servers[len].update_every = config.servers[len].update_every * 1000;
566
567
this.serviceExecute(config.servers[len].name, config.servers[len].url, config.servers[len].update_every);
568
added++;
node.d/node_modules/asn1.js
new
+20
@@ -0,0 +1,20 @@
1
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2
+
3
+// If you have no idea what ASN.1 or BER is, see this:
4
+// ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
5
+
6
+var Ber = require('./ber/index');
7
+
8
+
9
+
10
+///--- Exported API
11
+
12
+module.exports = {
13
+
14
+ Ber: Ber,
15
+
16
+ BerReader: Ber.Reader,
17
+
18
+ BerWriter: Ber.Writer
19
+
20
+};
node.d/node_modules/ber/errors.js
new
+13
@@ -0,0 +1,13 @@
1
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2
+
3
+
4
+module.exports = {
5
+
6
+ newInvalidAsn1Error: function(msg) {
7
+ var e = new Error();
8
+ e.name = 'InvalidAsn1Error';
9
+ e.message = msg || '';
10
+ return e;
11
+ }
12
+
13
+};
node.d/node_modules/ber/index.js
new
+27
@@ -0,0 +1,27 @@
1
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2
+
3
+var errors = require('./errors');
4
+var types = require('./types');
5
+
6
+var Reader = require('./reader');
7
+var Writer = require('./writer');
8
+
9
+
10
+///--- Exports
11
+
12
+module.exports = {
13
+
14
+ Reader: Reader,
15
+
16
+ Writer: Writer
17
+
18
+};
19
+
20
+for (var t in types) {
21
+ if (types.hasOwnProperty(t))
22
+ module.exports[t] = types[t];
23
+}
24
+for (var e in errors) {
25
+ if (errors.hasOwnProperty(e))
26
+ module.exports[e] = errors[e];
27
+}
node.d/node_modules/ber/reader.js
new
+261
@@ -0,0 +1,261 @@
1
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2
+
3
+var assert = require('assert');
4
+
5
+var ASN1 = require('./types');
6
+var errors = require('./errors');
7
+
8
+
9
+///--- Globals
10
+
11
+var newInvalidAsn1Error = errors.newInvalidAsn1Error;
12
+
13
+
14
+
15
+///--- API
16
+
17
+function Reader(data) {
18
+ if (!data || !Buffer.isBuffer(data))
19
+ throw new TypeError('data must be a node Buffer');
20
+
21
+ this._buf = data;
22
+ this._size = data.length;
23
+
24
+ // These hold the "current" state
25
+ this._len = 0;
26
+ this._offset = 0;
27
+}
28
+
29
+Object.defineProperty(Reader.prototype, 'length', {
30
+ enumerable: true,
31
+ get: function () { return (this._len); }
32
+});
33
+
34
+Object.defineProperty(Reader.prototype, 'offset', {
35
+ enumerable: true,
36
+ get: function () { return (this._offset); }
37
+});
38
+
39
+Object.defineProperty(Reader.prototype, 'remain', {
40
+ get: function () { return (this._size - this._offset); }
41
+});
42
+
43
+Object.defineProperty(Reader.prototype, 'buffer', {
44
+ get: function () { return (this._buf.slice(this._offset)); }
45
+});
46
+
47
+
48
+/**
49
+ * Reads a single byte and advances offset; you can pass in `true` to make this
50
+ * a "peek" operation (i.e., get the byte, but don't advance the offset).
51
+ *
52
+ * @param {Boolean} peek true means don't move offset.
53
+ * @return {Number} the next byte, null if not enough data.
54
+ */
55
+Reader.prototype.readByte = function(peek) {
56
+ if (this._size - this._offset < 1)
57
+ return null;
58
+
59
+ var b = this._buf[this._offset] & 0xff;
60
+
61
+ if (!peek)
62
+ this._offset += 1;
63
+
64
+ return b;
65
+};
66
+
67
+
68
+Reader.prototype.peek = function() {
69
+ return this.readByte(true);
70
+};
71
+
72
+
73
+/**
74
+ * Reads a (potentially) variable length off the BER buffer. This call is
75
+ * not really meant to be called directly, as callers have to manipulate
76
+ * the internal buffer afterwards.
77
+ *
78
+ * As a result of this call, you can call `Reader.length`, until the
79
+ * next thing called that does a readLength.
80
+ *
81
+ * @return {Number} the amount of offset to advance the buffer.
82
+ * @throws {InvalidAsn1Error} on bad ASN.1
83
+ */
84
+Reader.prototype.readLength = function(offset) {
85
+ if (offset === undefined)
86
+ offset = this._offset;
87
+
88
+ if (offset >= this._size)
89
+ return null;
90
+
91
+ var lenB = this._buf[offset++] & 0xff;
92
+ if (lenB === null)
93
+ return null;
94
+
95
+ if ((lenB & 0x80) == 0x80) {
96
+ lenB &= 0x7f;
97
+
98
+ if (lenB == 0)
99
+ throw newInvalidAsn1Error('Indefinite length not supported');
100
+
101
+ if (lenB > 4)
102
+ throw newInvalidAsn1Error('encoding too long');
103
+
104
+ if (this._size - offset < lenB)
105
+ return null;
106
+
107
+ this._len = 0;
108
+ for (var i = 0; i < lenB; i++)
109
+ this._len = (this._len << 8) + (this._buf[offset++] & 0xff);
110
+
111
+ } else {
112
+ // Wasn't a variable length
113
+ this._len = lenB;
114
+ }
115
+
116
+ return offset;
117
+};
118
+
119
+
120
+/**
121
+ * Parses the next sequence in this BER buffer.
122
+ *
123
+ * To get the length of the sequence, call `Reader.length`.
124
+ *
125
+ * @return {Number} the sequence's tag.
126
+ */
127
+Reader.prototype.readSequence = function(tag) {
128
+ var seq = this.peek();
129
+ if (seq === null)
130
+ return null;
131
+ if (tag !== undefined && tag !== seq)
132
+ throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
133
+ ': got 0x' + seq.toString(16));
134
+
135
+ var o = this.readLength(this._offset + 1); // stored in `length`
136
+ if (o === null)
137
+ return null;
138
+
139
+ this._offset = o;
140
+ return seq;
141
+};
142
+
143
+
144
+Reader.prototype.readInt = function() {
145
+ return this._readTag(ASN1.Integer);
146
+};
147
+
148
+
149
+Reader.prototype.readBoolean = function() {
150
+ return (this._readTag(ASN1.Boolean) === 0 ? false : true);
151
+};
152
+
153
+
154
+Reader.prototype.readEnumeration = function() {
155
+ return this._readTag(ASN1.Enumeration);
156
+};
157
+
158
+
159
+Reader.prototype.readString = function(tag, retbuf) {
160
+ if (!tag)
161
+ tag = ASN1.OctetString;
162
+
163
+ var b = this.peek();
164
+ if (b === null)
165
+ return null;
166
+
167
+ if (b !== tag)
168
+ throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
169
+ ': got 0x' + b.toString(16));
170
+
171
+ var o = this.readLength(this._offset + 1); // stored in `length`
172
+
173
+ if (o === null)
174
+ return null;
175
+
176
+ if (this.length > this._size - o)
177
+ return null;
178
+
179
+ this._offset = o;
180
+
181
+ if (this.length === 0)
182
+ return retbuf ? new Buffer(0) : '';
183
+
184
+ var str = this._buf.slice(this._offset, this._offset + this.length);
185
+ this._offset += this.length;
186
+
187
+ return retbuf ? str : str.toString('utf8');
188
+};
189
+
190
+Reader.prototype.readOID = function(tag) {
191
+ if (!tag)
192
+ tag = ASN1.OID;
193
+
194
+ var b = this.readString(tag, true);
195
+ if (b === null)
196
+ return null;
197
+
198
+ var values = [];
199
+ var value = 0;
200
+
201
+ for (var i = 0; i < b.length; i++) {
202
+ var byte = b[i] & 0xff;
203
+
204
+ value <<= 7;
205
+ value += byte & 0x7f;
206
+ if ((byte & 0x80) == 0) {
207
+ values.push(value);
208
+ value = 0;
209
+ }
210
+ }
211
+
212
+ value = values.shift();
213
+ values.unshift(value % 40);
214
+ values.unshift((value / 40) >> 0);
215
+
216
+ return values.join('.');
217
+};
218
+
219
+
220
+Reader.prototype._readTag = function(tag) {
221
+ assert.ok(tag !== undefined);
222
+
223
+ var b = this.peek();
224
+
225
+ if (b === null)
226
+ return null;
227
+
228
+ if (b !== tag)
229
+ throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
230
+ ': got 0x' + b.toString(16));
231
+
232
+ var o = this.readLength(this._offset + 1); // stored in `length`
233
+ if (o === null)
234
+ return null;
235
+
236
+ if (this.length > 4)
237
+ throw newInvalidAsn1Error('Integer too long: ' + this.length);
238
+
239
+ if (this.length > this._size - o)
240
+ return null;
241
+ this._offset = o;
242
+
243
+ var fb = this._buf[this._offset];
244
+ var value = 0;
245
+
246
+ for (var i = 0; i < this.length; i++) {
247
+ value <<= 8;
248
+ value |= (this._buf[this._offset++] & 0xff);
249
+ }
250
+
251
+ if ((fb & 0x80) == 0x80 && i !== 4)
252
+ value -= (1 << (i * 8));
253
+
254
+ return value >> 0;
255
+};
256
+
257
+
258
+
259
+///--- Exported API
260
+
261
+module.exports = Reader;
node.d/node_modules/ber/types.js
new
+36
@@ -0,0 +1,36 @@
1
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2
+
3
+
4
+module.exports = {
5
+ EOC: 0,
6
+ Boolean: 1,
7
+ Integer: 2,
8
+ BitString: 3,
9
+ OctetString: 4,
10
+ Null: 5,
11
+ OID: 6,
12
+ ObjectDescriptor: 7,
13
+ External: 8,
14
+ Real: 9, // float
15
+ Enumeration: 10,
16
+ PDV: 11,
17
+ Utf8String: 12,
18
+ RelativeOID: 13,
19
+ Sequence: 16,
20
+ Set: 17,
21
+ NumericString: 18,
22
+ PrintableString: 19,
23
+ T61String: 20,
24
+ VideotexString: 21,
25
+ IA5String: 22,
26
+ UTCTime: 23,
27
+ GeneralizedTime: 24,
28
+ GraphicString: 25,
29
+ VisibleString: 26,
30
+ GeneralString: 28,
31
+ UniversalString: 29,
32
+ CharacterString: 30,
33
+ BMPString: 31,
34
+ Constructor: 32,
35
+ Context: 128
36
+};
node.d/node_modules/ber/writer.js
new
+316
@@ -0,0 +1,316 @@
1
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2
+
3
+var assert = require('assert');
4
+var ASN1 = require('./types');
5
+var errors = require('./errors');
6
+
7
+
8
+///--- Globals
9
+
10
+var newInvalidAsn1Error = errors.newInvalidAsn1Error;
11
+
12
+var DEFAULT_OPTS = {
13
+ size: 1024,
14
+ growthFactor: 8
15
+};
16
+
17
+
18
+///--- Helpers
19
+
20
+function merge(from, to) {
21
+ assert.ok(from);
22
+ assert.equal(typeof(from), 'object');
23
+ assert.ok(to);
24
+ assert.equal(typeof(to), 'object');
25
+
26
+ var keys = Object.getOwnPropertyNames(from);
27
+ keys.forEach(function(key) {
28
+ if (to[key])
29
+ return;
30
+
31
+ var value = Object.getOwnPropertyDescriptor(from, key);
32
+ Object.defineProperty(to, key, value);
33
+ });
34
+
35
+ return to;
36
+}
37
+
38
+
39
+
40
+///--- API
41
+
42
+function Writer(options) {
43
+ options = merge(DEFAULT_OPTS, options || {});
44
+
45
+ this._buf = new Buffer(options.size || 1024);
46
+ this._size = this._buf.length;
47
+ this._offset = 0;
48
+ this._options = options;
49
+
50
+ // A list of offsets in the buffer where we need to insert
51
+ // sequence tag/len pairs.
52
+ this._seq = [];
53
+}
54
+
55
+Object.defineProperty(Writer.prototype, 'buffer', {
56
+ get: function () {
57
+ if (this._seq.length)
58
+ throw new InvalidAsn1Error(this._seq.length + ' unended sequence(s)');
59
+
60
+ return (this._buf.slice(0, this._offset));
61
+ }
62
+});
63
+
64
+Writer.prototype.writeByte = function(b) {
65
+ if (typeof(b) !== 'number')
66
+ throw new TypeError('argument must be a Number');
67
+
68
+ this._ensure(1);
69
+ this._buf[this._offset++] = b;
70
+};
71
+
72
+
73
+Writer.prototype.writeInt = function(i, tag) {
74
+ if (typeof(i) !== 'number')
75
+ throw new TypeError('argument must be a Number');
76
+ if (typeof(tag) !== 'number')
77
+ tag = ASN1.Integer;
78
+
79
+ var sz = 4;
80
+
81
+ while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000 >> 0)) &&
82
+ (sz > 1)) {
83
+ sz--;
84
+ i <<= 8;
85
+ }
86
+
87
+ if (sz > 4)
88
+ throw new InvalidAsn1Error('BER ints cannot be > 0xffffffff');
89
+
90
+ this._ensure(2 + sz);
91
+ this._buf[this._offset++] = tag;
92
+ this._buf[this._offset++] = sz;
93
+
94
+ while (sz-- > 0) {
95
+ this._buf[this._offset++] = ((i & 0xff000000) >>> 24);
96
+ i <<= 8;
97
+ }
98
+
99
+};
100
+
101
+
102
+Writer.prototype.writeNull = function() {
103
+ this.writeByte(ASN1.Null);
104
+ this.writeByte(0x00);
105
+};
106
+
107
+
108
+Writer.prototype.writeEnumeration = function(i, tag) {
109
+ if (typeof(i) !== 'number')
110
+ throw new TypeError('argument must be a Number');
111
+ if (typeof(tag) !== 'number')
112
+ tag = ASN1.Enumeration;
113
+
114
+ return this.writeInt(i, tag);
115
+};
116
+
117
+
118
+Writer.prototype.writeBoolean = function(b, tag) {
119
+ if (typeof(b) !== 'boolean')
120
+ throw new TypeError('argument must be a Boolean');
121
+ if (typeof(tag) !== 'number')
122
+ tag = ASN1.Boolean;
123
+
124
+ this._ensure(3);
125
+ this._buf[this._offset++] = tag;
126
+ this._buf[this._offset++] = 0x01;
127
+ this._buf[this._offset++] = b ? 0xff : 0x00;
128
+};
129
+
130
+
131
+Writer.prototype.writeString = function(s, tag) {
132
+ if (typeof(s) !== 'string')
133
+ throw new TypeError('argument must be a string (was: ' + typeof(s) + ')');
134
+ if (typeof(tag) !== 'number')
135
+ tag = ASN1.OctetString;
136
+
137
+ var len = Buffer.byteLength(s);
138
+ this.writeByte(tag);
139
+ this.writeLength(len);
140
+ if (len) {
141
+ this._ensure(len);
142
+ this._buf.write(s, this._offset);
143
+ this._offset += len;
144
+ }
145
+};
146
+
147
+
148
+Writer.prototype.writeBuffer = function(buf, tag) {
149
+ if (typeof(tag) !== 'number')
150
+ throw new TypeError('tag must be a number');
151
+ if (!Buffer.isBuffer(buf))
152
+ throw new TypeError('argument must be a buffer');
153
+
154
+ this.writeByte(tag);
155
+ this.writeLength(buf.length);
156
+ this._ensure(buf.length);
157
+ buf.copy(this._buf, this._offset, 0, buf.length);
158
+ this._offset += buf.length;
159
+};
160
+
161
+
162
+Writer.prototype.writeStringArray = function(strings) {
163
+ if ((!strings instanceof Array))
164
+ throw new TypeError('argument must be an Array[String]');
165
+
166
+ var self = this;
167
+ strings.forEach(function(s) {
168
+ self.writeString(s);
169
+ });
170
+};
171
+
172
+// This is really to solve DER cases, but whatever for now
173
+Writer.prototype.writeOID = function(s, tag) {
174
+ if (typeof(s) !== 'string')
175
+ throw new TypeError('argument must be a string');
176
+ if (typeof(tag) !== 'number')
177
+ tag = ASN1.OID;
178
+
179
+ if (!/^([0-9]+\.){3,}[0-9]+$/.test(s))
180
+ throw new Error('argument is not a valid OID string');
181
+
182
+ function encodeOctet(bytes, octet) {
183
+ if (octet < 128) {
184
+ bytes.push(octet);
185
+ } else if (octet < 16384) {
186
+ bytes.push((octet >>> 7) | 0x80);
187
+ bytes.push(octet & 0x7F);
188
+ } else if (octet < 2097152) {
189
+ bytes.push((octet >>> 14) | 0x80);
190
+ bytes.push(((octet >>> 7) | 0x80) & 0xFF);
191
+ bytes.push(octet & 0x7F);
192
+ } else if (octet < 268435456) {
193
+ bytes.push((octet >>> 21) | 0x80);
194
+ bytes.push(((octet >>> 14) | 0x80) & 0xFF);
195
+ bytes.push(((octet >>> 7) | 0x80) & 0xFF);
196
+ bytes.push(octet & 0x7F);
197
+ } else {
198
+ bytes.push(((octet >>> 28) | 0x80) & 0xFF);
199
+ bytes.push(((octet >>> 21) | 0x80) & 0xFF);
200
+ bytes.push(((octet >>> 14) | 0x80) & 0xFF);
201
+ bytes.push(((octet >>> 7) | 0x80) & 0xFF);
202
+ bytes.push(octet & 0x7F);
203
+ }
204
+ }
205
+
206
+ var tmp = s.split('.');
207
+ var bytes = [];
208
+ bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10));
209
+ tmp.slice(2).forEach(function(b) {
210
+ encodeOctet(bytes, parseInt(b, 10));
211
+ });
212
+
213
+ var self = this;
214
+ this._ensure(2 + bytes.length);
215
+ this.writeByte(tag);
216
+ this.writeLength(bytes.length);
217
+ bytes.forEach(function(b) {
218
+ self.writeByte(b);
219
+ });
220
+};
221
+
222
+
223
+Writer.prototype.writeLength = function(len) {
224
+ if (typeof(len) !== 'number')
225
+ throw new TypeError('argument must be a Number');
226
+
227
+ this._ensure(4);
228
+
229
+ if (len <= 0x7f) {
230
+ this._buf[this._offset++] = len;
231
+ } else if (len <= 0xff) {
232
+ this._buf[this._offset++] = 0x81;
233
+ this._buf[this._offset++] = len;
234
+ } else if (len <= 0xffff) {
235
+ this._buf[this._offset++] = 0x82;
236
+ this._buf[this._offset++] = len >> 8;
237
+ this._buf[this._offset++] = len;
238
+ } else if (len <= 0xffffff) {
239
+ this._buf[this._offset++] = 0x83;
240
+ this._buf[this._offset++] = len >> 16;
241
+ this._buf[this._offset++] = len >> 8;
242
+ this._buf[this._offset++] = len;
243
+ } else {
244
+ throw new InvalidAsn1ERror('Length too long (> 4 bytes)');
245
+ }
246
+};
247
+
248
+Writer.prototype.startSequence = function(tag) {
249
+ if (typeof(tag) !== 'number')
250
+ tag = ASN1.Sequence | ASN1.Constructor;
251
+
252
+ this.writeByte(tag);
253
+ this._seq.push(this._offset);
254
+ this._ensure(3);
255
+ this._offset += 3;
256
+};
257
+
258
+
259
+Writer.prototype.endSequence = function() {
260
+ var seq = this._seq.pop();
261
+ var start = seq + 3;
262
+ var len = this._offset - start;
263
+
264
+ if (len <= 0x7f) {
265
+ this._shift(start, len, -2);
266
+ this._buf[seq] = len;
267
+ } else if (len <= 0xff) {
268
+ this._shift(start, len, -1);
269
+ this._buf[seq] = 0x81;
270
+ this._buf[seq + 1] = len;
271
+ } else if (len <= 0xffff) {
272
+ this._buf[seq] = 0x82;
273
+ this._buf[seq + 1] = len >> 8;
274
+ this._buf[seq + 2] = len;
275
+ } else if (len <= 0xffffff) {
276
+ this._shift(start, len, 1);
277
+ this._buf[seq] = 0x83;
278
+ this._buf[seq + 1] = len >> 16;
279
+ this._buf[seq + 2] = len >> 8;
280
+ this._buf[seq + 3] = len;
281
+ } else {
282
+ throw new InvalidAsn1Error('Sequence too long');
283
+ }
284
+};
285
+
286
+
287
+Writer.prototype._shift = function(start, len, shift) {
288
+ assert.ok(start !== undefined);
289
+ assert.ok(len !== undefined);
290
+ assert.ok(shift);
291
+
292
+ this._buf.copy(this._buf, start + shift, start, start + len);
293
+ this._offset += shift;
294
+};
295
+
296
+Writer.prototype._ensure = function(len) {
297
+ assert.ok(len);
298
+
299
+ if (this._size - this._offset < len) {
300
+ var sz = this._size * this._options.growthFactor;
301
+ if (sz - this._offset < len)
302
+ sz += len;
303
+
304
+ var buf = new Buffer(sz);
305
+
306
+ this._buf.copy(buf, 0, 0, this._offset);
307
+ this._buf = buf;
308
+ this._size = sz;
309
+ }
310
+};
311
+
312
+
313
+
314
+///--- Exported API
315
+
316
+module.exports = Writer;
node.d/node_modules/net-snmp.js
new
+1466
@@ -0,0 +1,1466 @@
1
+
2
+// Copyright 2013 Stephen Vickers <stephen.vickers.sv@gmail.com>
3
+
4
+var ber = require ("asn1").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 (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
+ if (varbind.type == ObjectType.NoSuchObject
137
+ || varbind.type == ObjectType.NoSuchInstance
138
+ || varbind.type == ObjectType.EndOfMibView)
139
+ return true;
140
+ else
141
+ return false;
142
+}
143
+
144
+function varbindError (varbind) {
145
+ return (ObjectType[varbind.type] || "NotAnError") + ": " + varbind.oid;
146
+}
147
+
148
+function oidFollowsOid (oidString, nextString) {
149
+ var oid = {str: oidString, len: oidString.length, idx: 0};
150
+ var next = {str: nextString, len: nextString.length, idx: 0};
151
+ var dotCharCode = ".".charCodeAt (0);
152
+
153
+ function getNumber (item) {
154
+ var n = 0;
155
+ if (item.idx >= item.len)
156
+ return null;
157
+ while (item.idx < item.len) {
158
+ var charCode = item.str.charCodeAt (item.idx++);
159
+ if (charCode == dotCharCode)
160
+ return n;
161
+ n = (n ? (n * 10) : n) + (charCode - 48);
162
+ }
163
+ return n;
164
+ }
165
+
166
+ while (1) {
167
+ var oidNumber = getNumber (oid);
168
+ var nextNumber = getNumber (next);
169
+
170
+ if (oidNumber !== null) {
171
+ if (nextNumber !== null) {
172
+ if (nextNumber > oidNumber) {
173
+ return true;
174
+ } else if (nextNumber < oidNumber) {
175
+ return false;
176
+ }
177
+ } else {
178
+ return true;
179
+ }
180
+ } else {
181
+ return true;
182
+ }
183
+ }
184
+}
185
+
186
+function oidInSubtree (oidString, nextString) {
187
+ var oid = oidString.split (".");
188
+ var next = nextString.split (".");
189
+
190
+ if (oid.length > next.length)
191
+ return false;
192
+
193
+ for (var i = 0; i < oid.length; i++) {
194
+ if (next[i] != oid[i])
195
+ return false;
196
+ }
197
+
198
+ return true;
199
+}
200
+
201
+/**
202
+ ** Some SNMP agents produce integers on the wire such as 00 ff ff ff ff.
203
+ ** The ASN.1 BER parser we use throws an error when parsing this, which we
204
+ ** believe is correct. So, we decided not to bother the "asn1" developer(s)
205
+ ** with this, instead opting to work around it here.
206
+ **
207
+ ** If an integer is 5 bytes in length we check if the first byte is 0, and if so
208
+ ** simply drop it and parse it like it was a 4 byte integer, otherwise throw
209
+ ** an error since the integer is too large.
210
+ **/
211
+
212
+function readInt (buffer) {
213
+ return readUint (buffer, true);
214
+}
215
+
216
+function readUint (buffer, isSigned) {
217
+ buffer.readByte ();
218
+ var length = buffer.readByte ();
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
+ value = 0, signedBitSet = false;
229
+
230
+ for (var i = 0; i < length; i++) {
231
+ value *= 256;
232
+ value += buffer.readByte ();
233
+
234
+ if (isSigned && i <= 0) {
235
+ if ((value & 0x80) == 0x80)
236
+ signedBitSet = true;
237
+ }
238
+ }
239
+
240
+ if (signedBitSet)
241
+ value -= (1 << (i * 8));
242
+
243
+ return value;
244
+}
245
+
246
+function readUint64 (buffer) {
247
+ var value = buffer.readString (ObjectType.Counter64, true);
248
+
249
+ if (value.length > 8)
250
+ throw new RequestInvalidError ("64 bit unsigned integer too long '"
251
+ + value.length + "'")
252
+
253
+ return value;
254
+}
255
+
256
+function readVarbinds (buffer, varbinds) {
257
+ buffer.readSequence ();
258
+
259
+ while (1) {
260
+ buffer.readSequence ();
261
+ var oid = buffer.readOID ();
262
+ var type = buffer.peek ();
263
+
264
+ if (type == null)
265
+ break;
266
+
267
+ var value;
268
+
269
+ if (type == ObjectType.Boolean) {
270
+ value = buffer.readBoolean ();
271
+ } else if (type == ObjectType.Integer) {
272
+ value = readInt (buffer);
273
+ } else if (type == ObjectType.OctetString) {
274
+ value = buffer.readString (null, true);
275
+ } else if (type == ObjectType.Null) {
276
+ buffer.readByte ();
277
+ buffer.readByte ();
278
+ value = null;
279
+ } else if (type == ObjectType.OID) {
280
+ value = buffer.readOID ();
281
+ } else if (type == ObjectType.IpAddress) {
282
+ var bytes = buffer.readString (ObjectType.IpAddress, true);
283
+ if (bytes.length != 4)
284
+ throw new ResponseInvalidError ("Length '" + bytes.length
285
+ + "' of IP address '" + bytes.toString ("hex")
286
+ + "' is not 4");
287
+ value = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
288
+ } else if (type == ObjectType.Counter) {
289
+ value = readUint (buffer);
290
+ } else if (type == ObjectType.Gauge) {
291
+ value = readUint (buffer);
292
+ } else if (type == ObjectType.TimeTicks) {
293
+ value = readUint (buffer);
294
+ } else if (type == ObjectType.Opaque) {
295
+ value = buffer.readString (ObjectType.Opaque, true);
296
+ } else if (type == ObjectType.Counter64) {
297
+ value = readUint64 (buffer);
298
+ } else if (type == ObjectType.NoSuchObject) {
299
+ buffer.readByte ();
300
+ buffer.readByte ();
301
+ value = null;
302
+ } else if (type == ObjectType.NoSuchInstance) {
303
+ buffer.readByte ();
304
+ buffer.readByte ();
305
+ value = null;
306
+ } else if (type == ObjectType.EndOfMibView) {
307
+ buffer.readByte ();
308
+ buffer.readByte ();
309
+ value = null;
310
+ } else {
311
+ throw new ResponseInvalidError ("Unknown type '" + type
312
+ + "' in response");
313
+ }
314
+
315
+ varbinds.push ({
316
+ oid: oid,
317
+ type: type,
318
+ value: value
319
+ });
320
+ }
321
+}
322
+
323
+function writeUint (buffer, type, value) {
324
+ var b = new Buffer (4);
325
+ b.writeUInt32BE (value, 0);
326
+ buffer.writeBuffer (b, type);
327
+}
328
+
329
+function writeUint64 (buffer, value) {
330
+ if (value.length > 8)
331
+ throw new RequestInvalidError ("64 bit unsigned integer too long '"
332
+ + value.length + "'")
333
+ buffer.writeBuffer (value, ObjectType.Counter64);
334
+}
335
+
336
+function writeVarbinds (buffer, varbinds) {
337
+ buffer.startSequence ();
338
+ for (var i = 0; i < varbinds.length; i++) {
339
+ buffer.startSequence ();
340
+ buffer.writeOID (varbinds[i].oid);
341
+
342
+ if (varbinds[i].type && varbinds[i].hasOwnProperty("value")) {
343
+ var type = varbinds[i].type;
344
+ var value = varbinds[i].value;
345
+
346
+ if (type == ObjectType.Boolean) {
347
+ buffer.writeBoolean (value ? true : false);
348
+ } else if (type == ObjectType.Integer) { // also Integer32
349
+ buffer.writeInt (value);
350
+ } else if (type == ObjectType.OctetString) {
351
+ if (typeof value == "string")
352
+ buffer.writeString (value);
353
+ else
354
+ buffer.writeBuffer (value, ObjectType.OctetString);
355
+ } else if (type == ObjectType.Null) {
356
+ buffer.writeNull ();
357
+ } else if (type == ObjectType.OID) {
358
+ buffer.writeOID (value);
359
+ } else if (type == ObjectType.IpAddress) {
360
+ var bytes = value.split (".");
361
+ if (bytes.length != 4)
362
+ throw new RequestInvalidError ("Invalid IP address '"
363
+ + value + "'");
364
+ buffer.writeBuffer (new Buffer (bytes), 64);
365
+ } else if (type == ObjectType.Counter) { // also Counter32
366
+ writeUint (buffer, ObjectType.Counter, value);
367
+ } else if (type == ObjectType.Gauge) { // also Gauge32 & Unsigned32
368
+ writeUint (buffer, ObjectType.Gauge, value);
369
+ } else if (type == ObjectType.TimeTicks) {
370
+ writeUint (buffer, ObjectType.TimeTicks, value);
371
+ } else if (type == ObjectType.Opaque) {
372
+ buffer.writeBuffer (value, ObjectType.Opaque);
373
+ } else if (type == ObjectType.Counter64) {
374
+ writeUint64 (buffer, value);
375
+ } else {
376
+ throw new RequestInvalidError ("Unknown type '" + type
377
+ + "' in request");
378
+ }
379
+ } else {
380
+ buffer.writeNull ();
381
+ }
382
+
383
+ buffer.endSequence ();
384
+ };
385
+ buffer.endSequence ();
386
+}
387
+
388
+/*****************************************************************************
389
+ ** PDU class definitions
390
+ **/
391
+
392
+var SimplePdu = function (id, varbinds, options) {
393
+ this.id = id;
394
+ this.varbinds = varbinds;
395
+ this.options = options || {};
396
+};
397
+
398
+SimplePdu.prototype.toBuffer = function (buffer) {
399
+ buffer.startSequence (this.type);
400
+
401
+ buffer.writeInt (this.id);
402
+ buffer.writeInt ((this.type == PduType.GetBulkRequest)
403
+ ? (this.options.nonRepeaters || 0)
404
+ : 0);
405
+ buffer.writeInt ((this.type == PduType.GetBulkRequest)
406
+ ? (this.options.maxRepetitions || 0)
407
+ : 0);
408
+
409
+ writeVarbinds (buffer, this.varbinds);
410
+
411
+ buffer.endSequence ();
412
+};
413
+
414
+var GetBulkRequestPdu = function () {
415
+ this.type = PduType.GetBulkRequest;
416
+ GetBulkRequestPdu.super_.apply (this, arguments);
417
+};
418
+
419
+util.inherits (GetBulkRequestPdu, SimplePdu);
420
+
421
+var GetNextRequestPdu = function () {
422
+ this.type = PduType.GetNextRequest;
423
+ GetNextRequestPdu.super_.apply (this, arguments);
424
+};
425
+
426
+util.inherits (GetNextRequestPdu, SimplePdu);
427
+
428
+var GetResponsePdu = function (buffer) {
429
+ this.type = PduType.GetResponse;
430
+
431
+ buffer.readSequence (this.type);
432
+
433
+ this.id = buffer.readInt ();
434
+
435
+ this.errorStatus = buffer.readInt ();
436
+ this.errorIndex = buffer.readInt ();
437
+
438
+ this.varbinds = [];
439
+
440
+ readVarbinds (buffer, this.varbinds);
441
+};
442
+
443
+var GetRequestPdu = function () {
444
+ this.type = PduType.GetRequest;
445
+ GetRequestPdu.super_.apply (this, arguments);
446
+};
447
+
448
+util.inherits (GetRequestPdu, SimplePdu);
449
+
450
+var InformRequestPdu = function () {
451
+ this.type = PduType.InformRequest;
452
+ InformRequestPdu.super_.apply (this, arguments);
453
+};
454
+
455
+util.inherits (InformRequestPdu, SimplePdu);
456
+
457
+var SetRequestPdu = function () {
458
+ this.type = PduType.SetRequest;
459
+ SetRequestPdu.super_.apply (this, arguments);
460
+};
461
+
462
+util.inherits (SetRequestPdu, SimplePdu);
463
+
464
+var TrapPdu = function (typeOrOid, varbinds, options) {
465
+ this.type = PduType.Trap;
466
+
467
+ this.agentAddr = options.agentAddr || "127.0.0.1";
468
+ this.upTime = options.upTime;
469
+
470
+ if (typeof typeOrOid == "string") {
471
+ this.generic = TrapType.EnterpriseSpecific;
472
+ this.specific = parseInt (typeOrOid.match (/\.(\d+)$/)[1]);
473
+ this.enterprise = typeOrOid.replace (/\.(\d+)$/, "");
474
+ } else {
475
+ this.generic = typeOrOid;
476
+ this.specific = 0;
477
+ this.enterprise = "1.3.6.1.4.1";
478
+ }
479
+
480
+ this.varbinds = varbinds;
481
+};
482
+
483
+TrapPdu.prototype.toBuffer = function (buffer) {
484
+ buffer.startSequence (this.type);
485
+
486
+ buffer.writeOID (this.enterprise);
487
+ buffer.writeBuffer (new Buffer (this.agentAddr.split (".")),
488
+ ObjectType.IpAddress);
489
+ buffer.writeInt (this.generic);
490
+ buffer.writeInt (this.specific);
491
+ writeUint (buffer, ObjectType.TimeTicks,
492
+ this.upTime || Math.floor (process.uptime () * 100));
493
+
494
+ writeVarbinds (buffer, this.varbinds);
495
+
496
+ buffer.endSequence ();
497
+};
498
+
499
+var TrapV2Pdu = function () {
500
+ this.type = PduType.TrapV2;
501
+ TrapV2Pdu.super_.apply (this, arguments);
502
+};
503
+
504
+util.inherits (TrapV2Pdu, SimplePdu);
505
+
506
+/*****************************************************************************
507
+ ** Message class definitions
508
+ **/
509
+
510
+var RequestMessage = function (version, community, pdu) {
511
+ this.version = version;
512
+ this.community = community;
513
+ this.pdu = pdu;
514
+};
515
+
516
+RequestMessage.prototype.toBuffer = function () {
517
+ if (this.buffer)
518
+ return this.buffer;
519
+
520
+ var writer = new ber.Writer ();
521
+
522
+ writer.startSequence ();
523
+
524
+ writer.writeInt (this.version);
525
+ writer.writeString (this.community);
526
+
527
+ this.pdu.toBuffer (writer);
528
+
529
+ writer.endSequence ();
530
+
531
+ this.buffer = writer.buffer;
532
+
533
+ return this.buffer;
534
+};
535
+
536
+var ResponseMessage = function (buffer) {
537
+ var reader = new ber.Reader (buffer);
538
+
539
+ reader.readSequence ();
540
+
541
+ this.version = reader.readInt ();
542
+ this.community = reader.readString ();
543
+
544
+ var type = reader.peek ();
545
+
546
+ if (type == PduType.GetResponse) {
547
+ this.pdu = new GetResponsePdu (reader);
548
+ } else {
549
+ throw new ResponseInvalidError ("Unknown PDU type '" + type
550
+ + "' in response");
551
+ }
552
+}
553
+
554
+/*****************************************************************************
555
+ ** Session class definition
556
+ **/
557
+
558
+var Session = function (target, community, options) {
559
+ this.target = target || "127.0.0.1";
560
+ this.community = community || "public";
561
+
562
+ this.version = (options && options.version)
563
+ ? options.version
564
+ : Version1;
565
+
566
+ this.transport = (options && options.transport)
567
+ ? options.transport
568
+ : "udp4";
569
+ this.port = (options && options.port )
570
+ ? options.port
571
+ : 161;
572
+ this.trapPort = (options && options.trapPort )
573
+ ? options.trapPort
574
+ : 162;
575
+
576
+ this.retries = (options && (options.retries || options.retries == 0))
577
+ ? options.retries
578
+ : 1;
579
+ this.timeout = (options && options.timeout)
580
+ ? options.timeout
581
+ : 5000;
582
+
583
+ this.sourceAddress = (options && options.sourceAddress )
584
+ ? options.sourceAddress
585
+ : undefined;
586
+ this.sourcePort = (options && options.sourcePort )
587
+ ? parseInt(options.sourcePort)
588
+ : undefined;
589
+
590
+ this.reqs = {};
591
+ this.reqCount = 0;
592
+
593
+ this.dgram = dgram.createSocket (this.transport);
594
+ this.dgram.unref();
595
+
596
+ var me = this;
597
+ this.dgram.on ("message", me.onMsg.bind (me));
598
+ this.dgram.on ("close", me.onClose.bind (me));
599
+ this.dgram.on ("error", me.onError.bind (me));
600
+
601
+ if (this.sourceAddress || this.sourcePort)
602
+ req.dgram.bind (this.sourcePort, this.sourceAddress);
603
+};
604
+
605
+util.inherits (Session, events.EventEmitter);
606
+
607
+Session.prototype.close = function () {
608
+ this.dgram.close ();
609
+ return this;
610
+}
611
+
612
+Session.prototype.cancelRequests = function (error) {
613
+ for (id in this.reqs) {
614
+ var req = this.reqs[id];
615
+ this.unregisterRequest (req.id);
616
+ req.responseCb (error);
617
+ }
618
+}
619
+
620
+function _generateId () {
621
+ return Math.floor (Math.random () + Math.random () * 10000000)
622
+}
623
+
624
+Session.prototype.get = function (oids, responseCb) {
625
+ function feedCb (req, message) {
626
+ var pdu = message.pdu;
627
+ var varbinds = [];
628
+
629
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
630
+ req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
631
+ + "match response OIDs"));
632
+ } else {
633
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
634
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
635
+ req.responseCb (new ResponseInvalidError ("OID '"
636
+ + req.message.pdu.varbinds[i].oid
637
+ + "' in request at positiion '" + i + "' does not "
638
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
639
+ + "at position '" + i + "'"));
640
+ return;
641
+ } else {
642
+ varbinds.push (pdu.varbinds[i]);
643
+ }
644
+ }
645
+
646
+ req.responseCb (null, varbinds);
647
+ }
648
+ };
649
+
650
+ var pduVarbinds = [];
651
+
652
+ for (var i = 0; i < oids.length; i++) {
653
+ var varbind = {
654
+ oid: oids[i]
655
+ };
656
+ pduVarbinds.push (varbind);
657
+ }
658
+
659
+ this.simpleGet (GetRequestPdu, feedCb, pduVarbinds, responseCb);
660
+
661
+ return this;
662
+};
663
+
664
+Session.prototype.getBulk = function () {
665
+ var oids, nonRepeaters, maxRepetitions, responseCb;
666
+
667
+ if (arguments.length >= 4) {
668
+ oids = arguments[0];
669
+ nonRepeaters = arguments[1];
670
+ maxRepetitions = arguments[2];
671
+ responseCb = arguments[3];
672
+ } else if (arguments.length >= 3) {
673
+ oids = arguments[0];
674
+ nonRepeaters = arguments[1];
675
+ maxRepetitions = 10;
676
+ responseCb = arguments[2];
677
+ } else {
678
+ oids = arguments[0];
679
+ nonRepeaters = 0;
680
+ maxRepetitions = 10;
681
+ responseCb = arguments[1];
682
+ }
683
+
684
+ function feedCb (req, message) {
685
+ var pdu = message.pdu;
686
+ var varbinds = [];
687
+ var i = 0;
688
+
689
+ // first walk through and grab non-repeaters
690
+ if (pdu.varbinds.length < nonRepeaters) {
691
+ req.responseCb (new ResponseInvalidError ("Varbind count in "
692
+ + "response '" + pdu.varbinds.length + "' is less than "
693
+ + "non-repeaters '" + nonRepeaters + "' in request"));
694
+ } else {
695
+ for ( ; i < nonRepeaters; i++) {
696
+ if (isVarbindError (pdu.varbinds[i])) {
697
+ varbinds.push (pdu.varbinds[i]);
698
+ } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
699
+ pdu.varbinds[i].oid)) {
700
+ req.responseCb (new ResponseInvalidError ("OID '"
701
+ + req.message.pdu.varbinds[i].oid + "' in request at "
702
+ + "positiion '" + i + "' does not precede "
703
+ + "OID '" + pdu.varbinds[i].oid + "' in response "
704
+ + "at position '" + i + "'"));
705
+ return;
706
+ } else {
707
+ varbinds.push (pdu.varbinds[i]);
708
+ }
709
+ }
710
+ }
711
+
712
+ var repeaters = req.message.pdu.varbinds.length - nonRepeaters;
713
+
714
+ // secondly walk through and grab repeaters
715
+ if (pdu.varbinds.length % (repeaters)) {
716
+ req.responseCb (new ResponseInvalidError ("Varbind count in "
717
+ + "response '" + pdu.varbinds.length + "' is not a "
718
+ + "multiple of repeaters '" + repeaters
719
+ + "' plus non-repeaters '" + nonRepeaters + "' in request"));
720
+ } else {
721
+ while (i < pdu.varbinds.length) {
722
+ for (var j = 0; j < repeaters; j++, i++) {
723
+ var reqIndex = nonRepeaters + j;
724
+ var respIndex = i;
725
+
726
+ if (isVarbindError (pdu.varbinds[respIndex])) {
727
+ if (! varbinds[reqIndex])
728
+ varbinds[reqIndex] = [];
729
+ varbinds[reqIndex].push (pdu.varbinds[respIndex]);
730
+ } else if (! oidFollowsOid (
731
+ req.message.pdu.varbinds[reqIndex].oid,
732
+ pdu.varbinds[respIndex].oid)) {
733
+ req.responseCb (new ResponseInvalidError ("OID '"
734
+ + req.message.pdu.varbinds[reqIndex].oid
735
+ + "' in request at positiion '" + (reqIndex)
736
+ + "' does not precede OID '"
737
+ + pdu.varbinds[respIndex].oid
738
+ + "' in response at position '" + (respIndex) + "'"));
739
+ return;
740
+ } else {
741
+ if (! varbinds[reqIndex])
742
+ varbinds[reqIndex] = [];
743
+ varbinds[reqIndex].push (pdu.varbinds[respIndex]);
744
+ }
745
+ }
746
+ }
747
+ }
748
+
749
+ req.responseCb (null, varbinds);
750
+ };
751
+
752
+ var pduVarbinds = [];
753
+
754
+ for (var i = 0; i < oids.length; i++) {
755
+ var varbind = {
756
+ oid: oids[i]
757
+ };
758
+ pduVarbinds.push (varbind);
759
+ }
760
+
761
+ var options = {
762
+ nonRepeaters: nonRepeaters,
763
+ maxRepetitions: maxRepetitions
764
+ };
765
+
766
+ this.simpleGet (GetBulkRequestPdu, feedCb, pduVarbinds, responseCb,
767
+ options);
768
+
769
+ return this;
770
+};
771
+
772
+Session.prototype.getNext = function (oids, responseCb) {
773
+ function feedCb (req, message) {
774
+ var pdu = message.pdu;
775
+ var varbinds = [];
776
+
777
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
778
+ req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
779
+ + "match response OIDs"));
780
+ } else {
781
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
782
+ if (isVarbindError (pdu.varbinds[i])) {
783
+ varbinds.push (pdu.varbinds[i]);
784
+ } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
785
+ pdu.varbinds[i].oid)) {
786
+ req.responseCb (new ResponseInvalidError ("OID '"
787
+ + req.message.pdu.varbinds[i].oid + "' in request at "
788
+ + "positiion '" + i + "' does not precede "
789
+ + "OID '" + pdu.varbinds[i].oid + "' in response "
790
+ + "at position '" + i + "'"));
791
+ return;
792
+ } else {
793
+ varbinds.push (pdu.varbinds[i]);
794
+ }
795
+ }
796
+
797
+ req.responseCb (null, varbinds);
798
+ }
799
+ };
800
+
801
+ var pduVarbinds = [];
802
+
803
+ for (var i = 0; i < oids.length; i++) {
804
+ var varbind = {
805
+ oid: oids[i]
806
+ };
807
+ pduVarbinds.push (varbind);
808
+ }
809
+
810
+ this.simpleGet (GetNextRequestPdu, feedCb, pduVarbinds, responseCb);
811
+
812
+ return this;
813
+};
814
+
815
+Session.prototype.inform = function () {
816
+ var typeOrOid = arguments[0];;
817
+ var varbinds, options = {}, responseCb;
818
+
819
+ /**
820
+ ** Support the following signatures:
821
+ **
822
+ ** typeOrOid, varbinds, options, callback
823
+ ** typeOrOid, varbinds, callback
824
+ ** typeOrOid, options, callback
825
+ ** typeOrOid, callback
826
+ **/
827
+ if (arguments.length >= 4) {
828
+ varbinds = arguments[1];
829
+ options = arguments[2];
830
+ responseCb = arguments[3];
831
+ } else if (arguments.length >= 3) {
832
+ if (arguments[1].constructor != Array) {
833
+ varbinds = [];
834
+ options = arguments[1];
835
+ responseCb = arguments[2];
836
+ } else {
837
+ varbinds = arguments[1];
838
+ responseCb = arguments[2];
839
+ }
840
+ } else {
841
+ varbinds = [];
842
+ responseCb = arguments[1];
843
+ }
844
+
845
+ function feedCb (req, message) {
846
+ var pdu = message.pdu;
847
+ var varbinds = [];
848
+
849
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
850
+ req.responseCb (new ResponseInvalidError ("Inform OIDs do not "
851
+ + "match response OIDs"));
852
+ } else {
853
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
854
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
855
+ req.responseCb (new ResponseInvalidError ("OID '"
856
+ + req.message.pdu.varbinds[i].oid
857
+ + "' in inform at positiion '" + i + "' does not "
858
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
859
+ + "at position '" + i + "'"));
860
+ return;
861
+ } else {
862
+ varbinds.push (pdu.varbinds[i]);
863
+ }
864
+ }
865
+
866
+ req.responseCb (null, varbinds);
867
+ }
868
+ };
869
+
870
+ if (typeof typeOrOid != "string")
871
+ typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
872
+
873
+ var pduVarbinds = [
874
+ {
875
+ oid: "1.3.6.1.2.1.1.3.0",
876
+ type: ObjectType.TimeTicks,
877
+ value: options.upTime || Math.floor (process.uptime () * 100)
878
+ },
879
+ {
880
+ oid: "1.3.6.1.6.3.1.1.4.1.0",
881
+ type: ObjectType.OID,
882
+ value: typeOrOid
883
+ }
884
+ ];
885
+
886
+ for (var i = 0; i < varbinds.length; i++) {
887
+ var varbind = {
888
+ oid: varbinds[i].oid,
889
+ type: varbinds[i].type,
890
+ value: varbinds[i].value
891
+ };
892
+ pduVarbinds.push (varbind);
893
+ }
894
+
895
+ options.port = this.trapPort;
896
+
897
+ this.simpleGet (InformRequestPdu, feedCb, pduVarbinds, responseCb, options);
898
+
899
+ return this;
900
+};
901
+
902
+Session.prototype.onClose = function () {
903
+ this.cancelRequests (new Error ("Socket forcibly closed"));
904
+ this.emit ("close");
905
+};
906
+
907
+Session.prototype.onError = function (error) {
908
+ this.emit (error);
909
+};
910
+
911
+Session.prototype.onMsg = function (buffer, remote) {
912
+ try {
913
+ var message = new ResponseMessage (buffer);
914
+ } catch (error) {
915
+ this.emit("error", error);
916
+ }
917
+
918
+ var req = this.unregisterRequest (message.pdu.id);
919
+ if (! req)
920
+ return;
921
+
922
+ try {
923
+ if (message.version != req.message.version) {
924
+ req.responseCb (req, new ResponseInvalidError ("Version in request '"
925
+ + req.message.version + "' does not match version in "
926
+ + "response '" + message.version));
927
+ } else if (message.community != req.message.community) {
928
+ req.responseCb (req, new ResponseInvalidError ("Community '"
929
+ + req.message.community + "' in request does not match "
930
+ + "community '" + message.community + "' in response"));
931
+ } else if (message.pdu.type == PduType.GetResponse) {
932
+ req.onResponse (req, message);
933
+ } else {
934
+ req.responseCb (req, new ResponseInvalidError ("Unknown PDU type '"
935
+ + message.pdu.type + "' in response"));
936
+ }
937
+ } catch (error) {
938
+ req.responseCb (req, error);
939
+ }
940
+};
941
+
942
+Session.prototype.onSimpleGetResponse = function (req, message) {
943
+ var pdu = message.pdu;
944
+
945
+ if (pdu.errorStatus > 0) {
946
+ var statusString = ErrorStatus[pdu.errorStatus]
947
+ || ErrorStatus.GeneralError;
948
+ var statusCode = ErrorStatus[statusString]
949
+ || ErrorStatus[ErrorStatus.GeneralError];
950
+
951
+ if (pdu.errorIndex <= 0 || pdu.errorIndex > pdu.varbinds.length) {
952
+ req.responseCb (new RequestFailedError (statusString, statusCode));
953
+ } else {
954
+ var oid = pdu.varbinds[pdu.errorIndex - 1].oid;
955
+ var error = new RequestFailedError (statusString + ": " + oid,
956
+ statusCode);
957
+ req.responseCb (error);
958
+ }
959
+ } else {
960
+ req.feedCb (req, message);
961
+ }
962
+};
963
+
964
+Session.prototype.registerRequest = function (req) {
965
+ if (! this.reqs[req.id]) {
966
+ this.reqs[req.id] = req;
967
+ if (this.reqCount <= 0)
968
+ this.dgram.ref();
969
+ this.reqCount++;
970
+ }
971
+ var me = this;
972
+ req.timer = setTimeout (function () {
973
+ if (req.retries-- > 0) {
974
+ me.send (req);
975
+ } else {
976
+ me.unregisterRequest (req.id);
977
+ req.responseCb (new RequestTimedOutError (
978
+ "Request timed out"));
979
+ }
980
+ }, req.timeout);
981
+};
982
+
983
+Session.prototype.send = function (req, noWait) {
984
+ try {
985
+ var me = this;
986
+
987
+ var buffer = req.message.toBuffer ();
988
+
989
+ this.dgram.send (buffer, 0, buffer.length, req.port, this.target,
990
+ function (error, bytes) {
991
+ if (error) {
992
+ req.responseCb (error);
993
+ } else {
994
+ if (noWait) {
995
+ req.responseCb (null);
996
+ } else {
997
+ me.registerRequest (req);
998
+ }
999
+ }
1000
+ });
1001
+ } catch (error) {
1002
+ req.responseCb (error);
1003
+ }
1004
+
1005
+ return this;
1006
+};
1007
+
1008
+Session.prototype.set = function (varbinds, responseCb) {
1009
+ function feedCb (req, message) {
1010
+ var pdu = message.pdu;
1011
+ var varbinds = [];
1012
+
1013
+ if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1014
+ req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
1015
+ + "match response OIDs"));
1016
+ } else {
1017
+ for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1018
+ if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1019
+ req.responseCb (new ResponseInvalidError ("OID '"
1020
+ + req.message.pdu.varbinds[i].oid
1021
+ + "' in request at positiion '" + i + "' does not "
1022
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
1023
+ + "at position '" + i + "'"));
1024
+ return;
1025
+ } else {
1026
+ varbinds.push (pdu.varbinds[i]);
1027
+ }
1028
+ }
1029
+
1030
+ req.responseCb (null, varbinds);
1031
+ }
1032
+ };
1033
+
1034
+ var pduVarbinds = [];
1035
+
1036
+ for (var i = 0; i < varbinds.length; i++) {
1037
+ var varbind = {
1038
+ oid: varbinds[i].oid,
1039
+ type: varbinds[i].type,
1040
+ value: varbinds[i].value
1041
+ };
1042
+ pduVarbinds.push (varbind);
1043
+ }
1044
+
1045
+ this.simpleGet (SetRequestPdu, feedCb, pduVarbinds, responseCb);
1046
+
1047
+ return this;
1048
+};
1049
+
1050
+Session.prototype.simpleGet = function (pduClass, feedCb, varbinds,
1051
+ responseCb, options) {
1052
+ var req = {}
1053
+
1054
+ try {
1055
+ var id = _generateId ();
1056
+ var pdu = new pduClass (id, varbinds, options);
1057
+ var message = new RequestMessage (this.version, this.community, pdu);
1058
+
1059
+ req = {
1060
+ id: id,
1061
+ message: message,
1062
+ responseCb: responseCb,
1063
+ retries: this.retries,
1064
+ timeout: this.timeout,
1065
+ onResponse: this.onSimpleGetResponse,
1066
+ feedCb: feedCb,
1067
+ port: (options && options.port) ? options.port : this.port
1068
+ };
1069
+
1070
+ this.send (req);
1071
+ } catch (error) {
1072
+ if (req.responseCb)
1073
+ req.responseCb (error);
1074
+ }
1075
+};
1076
+
1077
+function subtreeCb (req, varbinds) {
1078
+ var done = 0;
1079
+
1080
+ for (var i = varbinds.length; i > 0; i--) {
1081
+ if (! oidInSubtree (req.baseOid, varbinds[i - 1].oid)) {
1082
+ done = 1;
1083
+ varbinds.pop ();
1084
+ }
1085
+ }
1086
+
1087
+ if (varbinds.length > 0)
1088
+ req.feedCb (varbinds);
1089
+
1090
+ if (done)
1091
+ return true;
1092
+}
1093
+
1094
+Session.prototype.subtree = function () {
1095
+ var me = this;
1096
+ var oid = arguments[0];
1097
+ var maxRepetitions, feedCb, doneCb;
1098
+
1099
+ if (arguments.length < 4) {
1100
+ maxRepetitions = 20;
1101
+ feedCb = arguments[1];
1102
+ doneCb = arguments[2];
1103
+ } else {
1104
+ maxRepetitions = arguments[1];
1105
+ feedCb = arguments[2];
1106
+ doneCb = arguments[3];
1107
+ }
1108
+
1109
+ var req = {
1110
+ feedCb: feedCb,
1111
+ doneCb: doneCb,
1112
+ maxRepetitions: maxRepetitions,
1113
+ baseOid: oid
1114
+ };
1115
+
1116
+ this.walk (oid, maxRepetitions, subtreeCb.bind (me, req), doneCb);
1117
+
1118
+ return this;
1119
+}
1120
+
1121
+function tableColumnsResponseCb (req, error) {
1122
+ if (error) {
1123
+ req.responseCb (error);
1124
+ } else if (req.error) {
1125
+ req.responseCb (req.error);
1126
+ } else {
1127
+ if (req.columns.length > 0) {
1128
+ var column = req.columns.pop ();
1129
+ var me = this;
1130
+ this.subtree (req.rowOid + column, req.maxRepetitions,
1131
+ tableColumnsFeedCb.bind (me, req),
1132
+ tableColumnsResponseCb.bind (me, req));
1133
+ } else {
1134
+ req.responseCb (null, req.table);
1135
+ }
1136
+ }
1137
+}
1138
+
1139
+function tableColumnsFeedCb (req, varbinds) {
1140
+ for (var i = 0; i < varbinds.length; i++) {
1141
+ if (isVarbindError (varbinds[i])) {
1142
+ req.error = new RequestFailedError (varbindError (varbind[i]));
1143
+ return true;
1144
+ }
1145
+
1146
+ var oid = varbinds[i].oid.replace (req.rowOid, "")
1147
+ if (oid && oid != varbinds[i].oid) {
1148
+ var match = oid.match (/^(\d+)\.(.+)$/);
1149
+ if (match && match[1] > 0) {
1150
+ if (! req.table[match[2]])
1151
+ req.table[match[2]] = {};
1152
+ req.table[match[2]][match[1]] = varbinds[i].value;
1153
+ }
1154
+ }
1155
+ }
1156
+}
1157
+
1158
+Session.prototype.tableColumns = function () {
1159
+ var me = this;
1160
+
1161
+ var oid = arguments[0];
1162
+ var columns = arguments[1];
1163
+ var maxRepetitions, responseCb;
1164
+
1165
+ if (arguments.length < 4) {
1166
+ responseCb = arguments[2];
1167
+ maxRepetitions = 20;
1168
+ } else {
1169
+ maxRepetitions = arguments[2];
1170
+ responseCb = arguments[3];
1171
+ }
1172
+
1173
+ var req = {
1174
+ responseCb: responseCb,
1175
+ maxRepetitions: maxRepetitions,
1176
+ baseOid: oid,
1177
+ rowOid: oid + ".1.",
1178
+ columns: columns.slice(0),
1179
+ table: {}
1180
+ };
1181
+
1182
+ if (req.columns.length > 0) {
1183
+ var column = req.columns.pop ();
1184
+ this.subtree (req.rowOid + column, maxRepetitions,
1185
+ tableColumnsFeedCb.bind (me, req),
1186
+ tableColumnsResponseCb.bind (me, req));
1187
+ }
1188
+
1189
+ return this;
1190
+}
1191
+
1192
+function tableResponseCb (req, error) {
1193
+ if (error)
1194
+ req.responseCb (error);
1195
+ else if (req.error)
1196
+ req.responseCb (req.error);
1197
+ else
1198
+ req.responseCb (null, req.table);
1199
+}
1200
+
1201
+function tableFeedCb (req, varbinds) {
1202
+ for (var i = 0; i < varbinds.length; i++) {
1203
+ if (isVarbindError (varbinds[i])) {
1204
+ req.error = new RequestFailedError (varbindError (varbind[i]));
1205
+ return true;
1206
+ }
1207
+
1208
+ var oid = varbinds[i].oid.replace (req.rowOid, "")
1209
+ if (oid && oid != varbinds[i].oid) {
1210
+ var match = oid.match (/^(\d+)\.(.+)$/);
1211
+ if (match && match[1] > 0) {
1212
+ if (! req.table[match[2]])
1213
+ req.table[match[2]] = {};
1214
+ req.table[match[2]][match[1]] = varbinds[i].value;
1215
+ }
1216
+ }
1217
+ }
1218
+}
1219
+
1220
+Session.prototype.table = function () {
1221
+ var me = this;
1222
+
1223
+ var oid = arguments[0];
1224
+ var maxRepetitions, responseCb;
1225
+
1226
+ if (arguments.length < 3) {
1227
+ responseCb = arguments[1];
1228
+ maxRepetitions = 20;
1229
+ } else {
1230
+ maxRepetitions = arguments[1];
1231
+ responseCb = arguments[2];
1232
+ }
1233
+
1234
+ var req = {
1235
+ responseCb: responseCb,
1236
+ maxRepetitions: maxRepetitions,
1237
+ baseOid: oid,
1238
+ rowOid: oid + ".1.",
1239
+ table: {}
1240
+ };
1241
+
1242
+ this.subtree (oid, maxRepetitions, tableFeedCb.bind (me, req),
1243
+ tableResponseCb.bind (me, req));
1244
+
1245
+ return this;
1246
+}
1247
+
1248
+Session.prototype.trap = function () {
1249
+ var req = {};
1250
+
1251
+ try {
1252
+ var typeOrOid = arguments[0];
1253
+ var varbinds, options = {}, responseCb;
1254
+
1255
+ /**
1256
+ ** Support the following signatures:
1257
+ **
1258
+ ** typeOrOid, varbinds, options, callback
1259
+ ** typeOrOid, varbinds, agentAddr, callback
1260
+ ** typeOrOid, varbinds, callback
1261
+ ** typeOrOid, agentAddr, callback
1262
+ ** typeOrOid, options, callback
1263
+ ** typeOrOid, callback
1264
+ **/
1265
+ if (arguments.length >= 4) {
1266
+ varbinds = arguments[1];
1267
+ if (typeof arguments[2] == "string") {
1268
+ options.agentAddr = arguments[2];
1269
+ } else if (arguments[2].constructor != Array) {
1270
+ options = arguments[2];
1271
+ }
1272
+ responseCb = arguments[3];
1273
+ } else if (arguments.length >= 3) {
1274
+ if (typeof arguments[1] == "string") {
1275
+ varbinds = [];
1276
+ options.agentAddr = arguments[1];
1277
+ } else if (arguments[1].constructor != Array) {
1278
+ varbinds = [];
1279
+ options = arguments[1];
1280
+ } else {
1281
+ varbinds = arguments[1];
1282
+ agentAddr = null;
1283
+ }
1284
+ responseCb = arguments[2];
1285
+ } else {
1286
+ varbinds = [];
1287
+ responseCb = arguments[1];
1288
+ }
1289
+
1290
+ var pdu, pduVarbinds = [];
1291
+
1292
+ for (var i = 0; i < varbinds.length; i++) {
1293
+ var varbind = {
1294
+ oid: varbinds[i].oid,
1295
+ type: varbinds[i].type,
1296
+ value: varbinds[i].value
1297
+ };
1298
+ pduVarbinds.push (varbind);
1299
+ }
1300
+
1301
+ var id = _generateId ();
1302
+
1303
+ if (this.version == Version2c) {
1304
+ if (typeof typeOrOid != "string")
1305
+ typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
1306
+
1307
+ pduVarbinds.unshift (
1308
+ {
1309
+ oid: "1.3.6.1.2.1.1.3.0",
1310
+ type: ObjectType.TimeTicks,
1311
+ value: options.upTime || Math.floor (process.uptime () * 100)
1312
+ },
1313
+ {
1314
+ oid: "1.3.6.1.6.3.1.1.4.1.0",
1315
+ type: ObjectType.OID,
1316
+ value: typeOrOid
1317
+ }
1318
+ );
1319
+
1320
+ pdu = new TrapV2Pdu (id, pduVarbinds, options);
1321
+ } else {
1322
+ pdu = new TrapPdu (typeOrOid, pduVarbinds, options);
1323
+ }
1324
+
1325
+ var message = new RequestMessage (this.version, this.community, pdu);
1326
+
1327
+ req = {
1328
+ id: id,
1329
+ message: message,
1330
+ responseCb: responseCb,
1331
+ port: this.trapPort
1332
+ };
1333
+
1334
+ this.send (req, true);
1335
+ } catch (error) {
1336
+ if (req.responseCb)
1337
+ req.responseCb (error);
1338
+ }
1339
+
1340
+ return this;
1341
+};
1342
+
1343
+Session.prototype.unregisterRequest = function (id) {
1344
+ var req = this.reqs[id];
1345
+ if (req) {
1346
+ delete this.reqs[id];
1347
+ clearTimeout (req.timer);
1348
+ delete req.timer;
1349
+ this.reqCount--;
1350
+ if (this.reqCount <= 0)
1351
+ this.dgram.unref();
1352
+ return req;
1353
+ } else {
1354
+ return null;
1355
+ }
1356
+};
1357
+
1358
+function walkCb (req, error, varbinds) {
1359
+ var done = 0;
1360
+ var oid;
1361
+
1362
+ if (error) {
1363
+ if (error instanceof RequestFailedError) {
1364
+ if (error.status != ErrorStatus.NoSuchName) {
1365
+ req.doneCb (error);
1366
+ return;
1367
+ } else {
1368
+ // signal the version 1 walk code below that it should stop
1369
+ done = 1;
1370
+ }
1371
+ } else {
1372
+ req.doneCb (error);
1373
+ return;
1374
+ }
1375
+ }
1376
+
1377
+ if (this.version == Version2c) {
1378
+ for (var i = varbinds[0].length; i > 0; i--) {
1379
+ if (varbinds[0][i - 1].type == ObjectType.EndOfMibView) {
1380
+ varbinds[0].pop ();
1381
+ done = 1;
1382
+ }
1383
+ }
1384
+ if (req.feedCb (varbinds[0]))
1385
+ done = 1;
1386
+ if (! done)
1387
+ oid = varbinds[0][varbinds[0].length - 1].oid;
1388
+ } else {
1389
+ if (! done) {
1390
+ if (req.feedCb (varbinds)) {
1391
+ done = 1;
1392
+ } else {
1393
+ oid = varbinds[0].oid;
1394
+ }
1395
+ }
1396
+ }
1397
+
1398
+ if (done)
1399
+ req.doneCb (null);
1400
+ else
1401
+ this.walk (oid, req.maxRepetitions, req.feedCb, req.doneCb,
1402
+ req.baseOid);
1403
+}
1404
+
1405
+Session.prototype.walk = function () {
1406
+ var me = this;
1407
+ var oid = arguments[0];
1408
+ var maxRepetitions, feedCb, doneCb, baseOid;
1409
+
1410
+ if (arguments.length < 4) {
1411
+ maxRepetitions = 20;
1412
+ feedCb = arguments[1];
1413
+ doneCb = arguments[2];
1414
+ } else {
1415
+ maxRepetitions = arguments[1];
1416
+ feedCb = arguments[2];
1417
+ doneCb = arguments[3];
1418
+ }
1419
+
1420
+ var req = {
1421
+ maxRepetitions: maxRepetitions,
1422
+ feedCb: feedCb,
1423
+ doneCb: doneCb
1424
+ };
1425
+
1426
+ if (this.version == Version2c)
1427
+ this.getBulk ([oid], 0, maxRepetitions,
1428
+ walkCb.bind (me, req));
1429
+ else
1430
+ this.getNext ([oid], walkCb.bind (me, req));
1431
+
1432
+ return this;
1433
+}
1434
+
1435
+/*****************************************************************************
1436
+ ** Exports
1437
+ **/
1438
+
1439
+exports.Session = Session;
1440
+
1441
+exports.createSession = function (target, community, version, options) {
1442
+ return new Session (target, community, version, options);
1443
+};
1444
+
1445
+exports.isVarbindError = isVarbindError;
1446
+exports.varbindError = varbindError;
1447
+
1448
+exports.Version1 = Version1;
1449
+exports.Version2c = Version2c;
1450
+
1451
+exports.ErrorStatus = ErrorStatus;
1452
+exports.TrapType = TrapType;
1453
+exports.ObjectType = ObjectType;
1454
+
1455
+exports.ResponseInvalidError = ResponseInvalidError;
1456
+exports.RequestInvalidError = RequestInvalidError;
1457
+exports.RequestFailedError = RequestFailedError;
1458
+exports.RequestTimedOutError = RequestTimedOutError;
1459
+
1460
+/**
1461
+ ** We've added this for testing.
1462
+ **/
1463
+exports.ObjectParser = {
1464
+ readInt: readInt,
1465
+ readUint: readUint
1466
+};
node.d/node_modules/netdata.js
+105
-82
@@ -43,7 +43,7 @@ var netdata = {
43
options: {
44
filename: __filename,
45
DEBUG: false,
46
- update_every: 1000,
46
+ update_every: 1,
47
},
48
49
chartAlgorithms: {
@@ -66,8 +66,61 @@ var netdata = {
66
67
processors: {
68
http: {
69
+ name: 'http',
70
70
- },
71
+ process: function(service, callback) {
72
+ if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': making ' + this.name + ' request: ' + netdata.stringify(service.request));
73
+
74
+ var req = http.request(service.request, function(response) {
75
+ if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');
76
+
77
+ var end = false;
78
+ var data = '';
79
+ response.setEncoding('utf8');
80
+
81
+ if(response.statusCode !== 200) {
82
+ if(end === false) {
83
+ service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');
84
+ end = true;
85
+ callback(null);
86
+ }
87
+ }
88
+
89
+ response.on('data', function(chunk) {
90
+ if(end === false) data += chunk;
91
+ });
92
+
93
+ response.on('error', function() {
94
+ if(end === false) {
95
+ service.error(': Read error, failed to get data.');
96
+ end = true;
97
+ callback(null);
98
+ }
99
+ });
100
+
101
+ response.on('end', function() {
102
+ if(end === false) {
103
+ if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');
104
+ end = true;
105
+ callback(data);
106
+ }
107
+ });
108
+ });
109
+
110
+ req.on('error', function(e) {
111
+ service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);
112
+ callback(null);
113
+ });
114
+
115
+ // write data to request body
116
+ if(typeof service.postData !== 'undefined' && service.request.method === 'POST') {
117
+ if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': posting data: ' + service.postData);
118
+ req.write(service.postData);
119
+ }
120
+
121
+ req.end();
122
+ }
123
+ }
124
},
125
126
stringify: function(obj) {
@@ -108,6 +161,7 @@ var netdata = {
161
service.running = false;
162
service.started = 0;
163
service.ended = 0;
164
+ service.next_run = new Date().getTime();
165
166
if(typeof service.update_every === 'undefined')
167
service.update_every = service.module.update_every;
@@ -118,106 +172,70 @@ var netdata = {
172
if(typeof service.processor === 'undefined')
173
service.processor = netdata.processors.http;
174
175
+ if(service.update_every < netdata.options.update_every)
176
+ service.update_every = netdata.options.update_every;
177
+
178
service.commit = function() {
179
if(this.added !== true) {
180
this.added = true;
181
+
182
+ var now = new Date().getTime();
183
+ while( this.next_run < now )
184
+ this.next_run += (this.update_every * 1000);
185
+
186
netdata.services.push(this);
187
if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': service committed.');
188
}
189
};
190
129
- service._processResponse = function(response, callback) {
130
- this.running = false;
131
- this.ended = new Date().getTime();
132
-
133
- if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': processing response (received it in ' + (this.ended - this.started).toString() + ' ms)');
134
-
135
- callback(this, response);
136
-
137
- this.module.active--;
138
- if(this.module.active < 0) {
139
- this.module.active = 0;
140
- if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': active module counter below zero.');
141
- }
142
-
143
- if(this.module.active === 0) {
144
- // check if we run under configure
145
- if(this.module.configure_callback !== null) {
146
- if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': configuration finish callback called from processResponse().');
147
- var ccallback = this.module.configure_callback;
148
- this.module.configure_callback = null;
149
- ccallback();
150
- }
151
- }
152
- };
153
-
191
service.execute = function(callback) {
192
this.module.active++;
193
this.running = true;
194
this.started = new Date().getTime();
195
this.updates++;
196
160
- if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': making request: ' + netdata.stringify(this.request));
197
+ if(netdata.options.DEBUG === true)
198
+ netdata.debug(this.module.name + ': ' + this.name + ': making ' + this.processor.name + ' request: ' + netdata.stringify(this));
199
162
- var req = http.request(this.request, function(response) {
163
- if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');
200
+ this.processor.process(this, function(response) {
201
+ service.ended = new Date().getTime();
202
+ service.duration = service.ended - service.started;
203
165
- var end = false;
166
- var data = '';
167
- response.setEncoding('utf8');
204
+ if(typeof response === 'undefined')
205
+ response = null;
206
169
- if(response.statusCode !== 200) {
170
- if(end === false) {
171
- service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');
172
- end = true;
173
- service._processResponse(null, callback);
174
- }
175
- }
207
+ if(response !== null)
208
+ service.errorClear();
209
177
- response.on('data', function(chunk) {
178
- if(end === false) data += chunk;
179
- });
210
+ if(netdata.options.DEBUG === true)
211
+ netdata.debug(service.module.name + ': ' + service.name + ': processing ' + service.processor.name + ' response (received in ' + (service.ended - service.started).toString() + ' ms)');
212
181
- response.on('error', function() {
182
- if(end === false) {
183
- service.error(': Read error, failed to get data.');
184
- end = true;
185
- service._processResponse(null, callback);
186
- }
187
- });
213
+ callback(service, response);
214
189
- response.on('end', function() {
190
- if(end === false) {
191
- service.errorClear();
192
- if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');
193
- end = true;
194
- service._processResponse(data, callback);
195
- }
196
- });
197
- });
215
+ service.running = false;
216
+ service.module.active--;
217
+ if(service.module.active < 0) {
218
+ service.module.active = 0;
219
+ if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': active module counter below zero.');
220
+ }
221
199
- req.on('error', function(e) {
200
- service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);
201
- service._processResponse(null, callback);
222
+ if(service.module.active === 0) {
223
+ // check if we run under configure
224
+ if(service.module.configure_callback !== null) {
225
+ if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': configuration finish callback called from processResponse().');
226
+ var ccallback = service.module.configure_callback;
227
+ service.module.configure_callback = null;
228
+ ccallback();
229
+ }
230
+ }
231
});
203
-
204
- // write data to request body
205
- if(typeof this.postData !== 'undefined' && this.request.method === 'POST') {
206
- if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': posting data: ' + this.postData);
207
- req.write(this.postData);
208
- }
209
-
210
- req.end();
232
};
233
234
service.update = function() {
235
if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': starting data collection...');
236
237
this.module.update(this, function() {
217
- service.ended = new Date().getTime();
218
- service.duration = service.ended - service.started;
238
if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': data collection ended in ' + service.duration.toString() + ' ms.');
220
- service.running = false;
239
});
240
};
241
@@ -345,7 +363,7 @@ var netdata = {
363
if(typeof(netdata.charts[id]) === 'undefined') {
364
netdata.charts[id] = {
365
_created: false,
348
- _updated: false,
366
+ _updated: true,
367
_began: false,
368
_counter: 0,
369
_last_updated: 0,
@@ -354,8 +372,8 @@ var netdata = {
372
name: id,
373
title: 'untitled chart',
374
units: 'a unit',
357
- family: id,
358
- category: id,
375
+ family: '',
376
+ category: '',
377
type: netdata.chartTypes.line,
378
priority: 0,
379
update_every: netdata.options.update_every,
@@ -408,7 +426,7 @@ var netdata = {
426
}
427
428
if(typeof(chart.update_every) !== 'undefined' && chart.update_every !== c.update_every) {
411
- if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every');
429
+ if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every from ' + c.update_every + ' to ' + chart.update_every);
430
c.update_every = chart.update_every;
431
c._updated = true;
432
}
@@ -486,16 +504,21 @@ var netdata = {
504
var service = netdata.services[len];
505
506
if(service.enabled === false || service.running === true) continue;
489
- if(now - service.ended < service.update_every) continue;
507
+ if(now <= service.next_run) continue;
508
509
service.update();
510
+
511
+ now = new Date().getTime();
512
+ while(service.next_run < now)
513
+ service.next_run += (service.update_every * 1000);
514
}
515
494
- setTimeout(netdata.runAllServices, 100);
516
+ // 1/10th of update_every in pause
517
+ setTimeout(netdata.runAllServices, netdata.options.update_every * 100);
518
},
519
520
start: function() {
498
- if(netdata.options.DEBUG === true) this.debug('started, services:');
521
+ if(netdata.options.DEBUG === true) this.debug('started, services: ' + netdata.stringify(this.services));
522
523
if(this.services.length === 0) {
524
this.disableNodePlugin();
@@ -524,7 +547,7 @@ var netdata = {
547
},
548
agent: new http.Agent({
549
keepAlive: true,
527
- keepAliveMsecs: netdata.options.update_every,
550
+ keepAliveMsecs: netdata.options.update_every * 1000,
551
maxSockets: 2, // it must be 2 to work
552
maxFreeSockets: 1
553
})
@@ -543,7 +566,7 @@ var netdata = {
566
module.update_every = this.options.update_every;
567
568
if(typeof config.update_every !== 'undefined')
546
- module.update_every = config.update_every * 1000;
569
+ module.update_every = config.update_every;
570
571
module.enable_autodetect = (config.enable_autodetect)?true:false;
572
node.d/sma_webbox.node.js
+6
-8
@@ -32,7 +32,7 @@ if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plug
32
var webbox = {
33
name: __filename,
34
enable_autodetect: true,
35
- update_every: 1000,
35
+ update_every: 1,
36
37
charts: {},
38
@@ -87,7 +87,7 @@ var webbox = {
87
category: 'sma_webbox_' + service.name, // the category of the chart
88
type: netdata.chartTypes.area, // the type of the chart
89
priority: 1000, // the priority relative to others in the same family and category
90
- update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
90
+ update_every: service.update_every, // the expected update frequency of the chart
91
dimensions: {
92
'GriPwr': {
93
id: 'GriPwr', // the unique id of the dimension
@@ -123,7 +123,7 @@ var webbox = {
123
category: 'sma_webbox_' + service.name, // the category of the chart
124
type: netdata.chartTypes.area, // the type of the chart
125
priority: 1000, // the priority relative to others in the same family and category
126
- update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
126
+ update_every: service.update_every, // the expected update frequency of the chart
127
dimensions: {
128
'GriEgyTdy': {
129
id: 'GriEgyTdy', // the unique id of the dimension
@@ -159,7 +159,7 @@ var webbox = {
159
category: 'sma_webbox_' + service.name, // the category of the chart
160
type: netdata.chartTypes.area, // the type of the chart
161
priority: 1000, // the priority relative to others in the same family and category
162
- update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
162
+ update_every: service.update_every, // the expected update frequency of the chart
163
dimensions: {
164
'GriEgyTot': {
165
id: 'GriEgyTot', // the unique id of the dimension
@@ -211,11 +211,9 @@ var webbox = {
211
while(len--) {
212
if(typeof config.servers[len].update_every === 'undefined')
213
config.servers[len].update_every = this.update_every;
214
- else
215
- config.servers[len].update_every = config.servers[len].update_every * 1000;
214
217
- if(config.servers[len].update_every < 5000)
218
- config.servers[len].update_every = 5000;
215
+ if(config.servers[len].update_every < 5)
216
+ config.servers[len].update_every = 5;
217
218
this.serviceExecute(config.servers[len].name, config.servers[len].hostname, config.servers[len].update_every);
219
added++;
node.d/snmp.node.js
new
+327
@@ -0,0 +1,327 @@
1
+'use strict';
2
+
3
+// This program will connect to one or more SNMP Agents
4
+
5
+// example configuration in /etc/netdata/snmp.conf
6
+/*
7
+{
8
+ "enable_autodetect": false,
9
+ "update_every": 5,
10
+ "servers": [
11
+ {
12
+ "hostname": "10.11.12.8",
13
+ "community": "public",
14
+ "update_every": 10,
15
+ "options": { "timeout": 10000 },
16
+ "charts": {
17
+ "snmp_switch.bandwidth_port1": {
18
+ "title": "Switch Bandwidth for port 1",
19
+ "units": "kilobits/s",
20
+ "type": "area",
21
+ "priority": 1,
22
+ "dimensions": {
23
+ "in": {
24
+ "oid": ".1.3.6.1.2.1.2.2.1.10.1",
25
+ "algorithm": "incremental",
26
+ "multiplier": 8,
27
+ "divisor": 1024
28
+ },
29
+ "out": {
30
+ "oid": ".1.3.6.1.2.1.2.2.1.16.1",
31
+ "algorithm": "incremental",
32
+ "multiplier": -8,
33
+ "divisor": 1024
34
+ }
35
+ }
36
+ },
37
+ "snmp_switch.bandwidth_port2": {
38
+ "title": "Switch Bandwidth for port 2",
39
+ "units": "kilobits/s",
40
+ "type": "area",
41
+ "priority": 1,
42
+ "dimensions": {
43
+ "in": {
44
+ "oid": ".1.3.6.1.2.1.2.2.1.10.2",
45
+ "algorithm": "incremental",
46
+ "multiplier": 8,
47
+ "divisor": 1024
48
+ },
49
+ "out": {
50
+ "oid": ".1.3.6.1.2.1.2.2.1.16.2",
51
+ "algorithm": "incremental",
52
+ "multiplier": -8,
53
+ "divisor": 1024
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ ]
60
+}
61
+*/
62
+
63
+// You can also give ranges of charts like the following.
64
+// This will append 1-24 to id, title, oid (on each dimension)
65
+// so that 24 charts will be created.
66
+/*
67
+{
68
+ "enable_autodetect": false,
69
+ "update_every": 10,
70
+ "servers": [
71
+ {
72
+ "hostname": "10.11.12.8",
73
+ "community": "public",
74
+ "update_every": 10,
75
+ "options": { "timeout": 20000 },
76
+ "charts": {
77
+ "snmp_switch.bandwidth_port": {
78
+ "title": "Switch Bandwidth for port ",
79
+ "units": "kilobits/s",
80
+ "type": "area",
81
+ "priority": 1,
82
+ "multiply_range": [ 1, 24 ],
83
+ "dimensions": {
84
+ "in": {
85
+ "oid": "1.3.6.1.2.1.2.2.1.10",
86
+ "algorithm": "incremental",
87
+ "multiplier": 8,
88
+ "divisor": 1024
89
+ },
90
+ "out": {
91
+ "oid": "1.3.6.1.2.1.2.2.1.16",
92
+ "algorithm": "incremental",
93
+ "multiplier": -8,
94
+ "divisor": 1024
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ ]
101
+}
102
+*/
103
+
104
+var net_snmp = require('net-snmp');
105
+var extend = require('extend');
106
+var netdata = require('netdata');
107
+
108
+if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin');
109
+
110
+netdata.processors.snmp = {
111
+ name: 'snmp',
112
+
113
+ process: function(service, callback) {
114
+ if(typeof service.snmp_oids === 'undefined' || service.snmp_oids === null || service.snmp_oids.length === 0) {
115
+ // this is the first time we see this service
116
+
117
+ if(netdata.options.DEBUG === true)
118
+ netdata.debug(service.module.name + ': ' + service.name + ': preparing ' + this.name + ' OIDs');
119
+
120
+ // build an index of all OIDs
121
+ service.snmp_oids_index = {};
122
+ for(var c in service.request.charts) {
123
+ // for each chart
124
+
125
+ if(netdata.options.DEBUG === true)
126
+ netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c);
127
+
128
+ for(var d in service.request.charts[c].dimensions) {
129
+ // for each dimension in the chart
130
+
131
+ if(netdata.options.DEBUG === true)
132
+ netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c + ', dimension: ' + d + ', OID: ' + service.request.charts[c].dimensions[d].oid);
133
+
134
+ // link it to the point we need to set the value to
135
+ service.snmp_oids_index[service.request.charts[c].dimensions[d].oid] = service.request.charts[c].dimensions[d];
136
+
137
+ // and set the value to null
138
+ service.request.charts[c].dimensions[d].value = null;
139
+ }
140
+ }
141
+ if(netdata.options.DEBUG === true)
142
+ netdata.debug(service.module.name + ': ' + service.name + ': indexed ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids_index));
143
+
144
+ // now create the array of OIDs needed by net-snmp
145
+ service.snmp_oids = new Array();
146
+ for(var o in service.snmp_oids_index)
147
+ service.snmp_oids.push(o);
148
+
149
+ if(netdata.options.DEBUG === true)
150
+ netdata.debug(service.module.name + ': ' + service.name + ': final list of ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids));
151
+ }
152
+
153
+ if(service.snmp_oids.length === 0) {
154
+ // no OIDs found for this service
155
+
156
+ if(netdata.options.DEBUG === true)
157
+ service.error('no OIDs to process.');
158
+
159
+ callback(null);
160
+ return;
161
+ }
162
+
163
+ if(typeof service.snmp_session === 'undefined' || service.snmp_session === null) {
164
+ // no SNMP session has been created for this service
165
+ // the SNMP session is just the initialization of NET-SNMP
166
+
167
+ if(netdata.options.DEBUG === true)
168
+ 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));
169
+
170
+ // create the SNMP session
171
+ service.snmp_session = net_snmp.createSession (service.request.hostname, service.request.community, service.request.options);
172
+
173
+ if(netdata.options.DEBUG === true)
174
+ netdata.debug(service.module.name + ': ' + service.name + ': got ' + this.name + ' session: ' + netdata.stringify(service.snmp_session));
175
+
176
+ // if we later need traps, this is how to do it:
177
+ //service.snmp_session.trap(net_snmp.TrapType.LinkDown, function(error) {
178
+ // if(error) console.error('trap error: ' + netdata.stringify(error));
179
+ //});
180
+ }
181
+
182
+ // do it, get the SNMP values for the sessions we need
183
+ service.snmp_session.get(service.snmp_oids, function(error, varbinds) {
184
+ var ok = 0, failed = 0;
185
+
186
+ if(error) {
187
+ service.error('Received error = ' + netdata.stringify(error) + ' varbinds = ' + netdata.stringify(varbinds));
188
+ }
189
+ else {
190
+ if(netdata.options.DEBUG === true)
191
+ netdata.debug(service.module.name + ': ' + service.name + ': got valid ' + service.module.name + ' response: ' + netdata.stringify(varbinds));
192
+
193
+ for(var i = 0; i < varbinds.length; i++) {
194
+ if(net_snmp.isVarbindError(varbinds[i])) {
195
+ if(netdata.options.DEBUG === true)
196
+ netdata.debug(service.module.name + ': ' + service.name + ': failed ' + service.module.name + ' get for OIDs ' + varbinds[i].oid);
197
+
198
+ service.error('OID ' + varbinds[i].oid + ' gave error: ' + snmp.varbindError(varbinds[i]));
199
+ service.snmp_oids_index[varbinds[i].oid].value = null;
200
+ failed++;
201
+ }
202
+ else {
203
+ if(netdata.options.DEBUG === true)
204
+ netdata.debug(service.module.name + ': ' + service.name + ': found ' + service.module.name + ' value of OIDs ' + varbinds[i].oid + " = " + varbinds[i].value);
205
+
206
+ service.snmp_oids_index[varbinds[i].oid].value = varbinds[i].value;
207
+ ok++;
208
+ }
209
+ }
210
+
211
+ if(netdata.options.DEBUG === true)
212
+ netdata.debug(service.module.name + ': ' + service.name + ': finished ' + service.module.name + ' with ' + ok + ' successful and ' + failed + ' failed values');
213
+ }
214
+
215
+ callback((ok > 0)?{ ok: ok, failed: failed }:null);
216
+ });
217
+ }
218
+};
219
+
220
+var snmp = {
221
+ name: __filename,
222
+ enable_autodetect: true,
223
+ update_every: 1,
224
+
225
+ charts: {},
226
+
227
+ processResponse: function(service, data) {
228
+ if(data !== null) {
229
+ if(service.added !== true)
230
+ service.commit();
231
+
232
+ for(var c in service.request.charts) {
233
+ var chart = snmp.charts[c];
234
+
235
+ if(typeof chart === 'undefined') {
236
+ chart = service.chart(c, service.request.charts[c]);
237
+ snmp.charts[c] = chart;
238
+ }
239
+
240
+ service.begin(chart);
241
+
242
+ for( var d in service.request.charts[c].dimensions )
243
+ if(service.request.charts[c].dimensions[d].value !== null)
244
+ service.set(d, service.request.charts[c].dimensions[d].value);
245
+
246
+ service.end();
247
+ }
248
+ }
249
+ },
250
+
251
+ // module.serviceExecute()
252
+ // this function is called only from this module
253
+ // its purpose is to prepare the request and call
254
+ // netdata.serviceExecute()
255
+ serviceExecute: function(conf) {
256
+ if(netdata.options.DEBUG === true)
257
+ netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', update_every: ' + conf.update_every);
258
+
259
+ var service = netdata.service({
260
+ name: conf.hostname,
261
+ request: conf,
262
+ update_every: conf.update_every,
263
+ module: this,
264
+ processor: netdata.processors.snmp
265
+ });
266
+
267
+ // multiply the charts, if required
268
+ for(var c in service.request.charts) {
269
+ if(netdata.options.DEBUG === true)
270
+ netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', examining chart: ' + c);
271
+
272
+ if(typeof service.request.charts[c].update_every === 'undefined')
273
+ service.request.charts[c].update_every = service.update_every;
274
+
275
+ if(typeof service.request.charts[c].multiply_range !== 'undefined') {
276
+ var from = service.request.charts[c].multiply_range[0];
277
+ var to = service.request.charts[c].multiply_range[1];
278
+ var prio = service.request.charts[c].priority || 1;
279
+
280
+ while(from <= to) {
281
+ var id = c + from.toString();
282
+ var chart = extend(true, {}, service.request.charts[c]);
283
+ chart.title += from.toString();
284
+ chart.priority = prio++;
285
+ for(var d in chart.dimensions) {
286
+ chart.dimensions[d].oid += '.' + from.toString();
287
+ }
288
+ service.request.charts[id] = chart;
289
+ from++;
290
+ }
291
+
292
+ delete service.request.charts[c];
293
+ }
294
+ }
295
+
296
+ service.execute(this.processResponse);
297
+ },
298
+
299
+ configure: function(config) {
300
+ var added = 0;
301
+
302
+ if(typeof(config.servers) !== 'undefined') {
303
+ var len = config.servers.length;
304
+ while(len--) {
305
+ if(typeof config.servers[len].update_every === 'undefined')
306
+ config.servers[len].update_every = this.update_every;
307
+
308
+ this.serviceExecute(config.servers[len]);
309
+ added++;
310
+ }
311
+ }
312
+
313
+ return added;
314
+ },
315
+
316
+ // module.update()
317
+ // this is called repeatidly to collect data, by calling
318
+ // service.execute()
319
+ update: function(service, callback) {
320
+ service.execute(function(serv, data) {
321
+ service.module.processResponse(serv, data);
322
+ callback();
323
+ });
324
+ },
325
+};
326
+
327
+module.exports = snmp;
plugins.d/node.d.plugin
+7
-7
@@ -9,7 +9,6 @@ var NETDATA_PLUGINS_DIR = process.env.NETDATA_PLUGINS_DIR || __dirname;
9
var NETDATA_CONFIG_DIR = process.env.NETDATA_CONFIG_DIR || '/etc/netdata';
10
var NETDATA_UPDATE_EVERY = process.env.NETDATA_UPDATE_EVERY || 1;
11
var NODE_D_DIR = NETDATA_PLUGINS_DIR + '/../node.d';
12
-NETDATA_UPDATE_EVERY = NETDATA_UPDATE_EVERY * 1000;
12
13
// make sure the modules are found
14
process.mainModule.paths.unshift(NODE_D_DIR + '/node_modules');
@@ -133,14 +132,14 @@ function dumpError(err) {
132
try {
133
var x = parseInt(val);
134
if(x > 0) {
136
- netdata.options.update_every = x * 1000;
135
+ netdata.options.update_every = x;
136
if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
137
netdata.options.update_every = NETDATA_UPDATE_EVERY;
138
netdata.debug('Update frequency ' + x + 's is too low');
139
}
140
141
found_number = true;
143
- netdata.debug('Update frequency set to ' + netdata.options.update_every + ' ms');
142
+ netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
143
}
144
else netdata.error('Ignoring parameter: ' + val);
145
}
@@ -155,9 +154,9 @@ function dumpError(err) {
154
});
155
}
156
158
-if(netdata.options.update_every < 1000) {
157
+if(netdata.options.update_every < 1) {
158
netdata.debug('Adjusting update frequency to 1 second');
160
- netdata.options.update_every = 1000;
159
+ netdata.options.update_every = 1;
160
}
161
162
// --------------------------------------------------------------------------------------------------------------------
@@ -174,7 +173,7 @@ function findModules() {
173
var n = files[len].substring(0, m.index);
174
175
if(typeof(netdata.options.modules[n]) === 'undefined')
177
- netdata.options.modules[n] = { enabled: netdata.options.modules_enable_all };
176
+ netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };
177
178
if(netdata.options.modules[n].enabled === true) {
179
netdata.options.modules[n].name = n;
@@ -201,7 +200,7 @@ function findModules() {
200
// load its configuration
201
var c = {
202
enable_autodetect: netdata.options.modules_enable_autodetect,
204
- update_every: Math.round(netdata.options.update_every / 1000)
203
+ update_every: netdata.options.update_every
204
};
205
try {
206
netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
@@ -239,6 +238,7 @@ function findModules() {
238
}
239
}
240
241
+ // netdata.debug(netdata.options.modules);
242
return found;
243
}
244