net-snmp 3.26.3 → 3.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/index.js +142 -12
- package/package.json +10 -1
- package/.claude/skills/git-commit/SKILL.md +0 -54
- package/.claude/skills/prepare-release/SKILL.md +0 -97
- package/.claude/skills/propose-action/SKILL.md +0 -111
- package/.claude/skills/publish-release/SKILL.md +0 -68
- package/.github/FUNDING.yml +0 -1
- package/.travis.yml +0 -13
- package/.vscode/launch.json +0 -249
- package/eslint.config.js +0 -98
- package/example/test.js +0 -70
- package/test/README-test-coverage.md +0 -76
- package/test/TEST-MIB.mib +0 -210
- package/test/cast-set-value.test.js +0 -200
- package/test/crypto.test.js +0 -384
- package/test/dgram-module.test.js +0 -71
- package/test/mib.test.js +0 -139
- package/test/object-types.test.js +0 -269
- package/test/oid-in-subtree.test.js +0 -36
- package/test/receiver-test.sh +0 -83
- package/test/snmp-test.sh +0 -122
- package/test/snmpv3-auth-failures.test.js +0 -331
- package/test/strict-int-range-checks.test.js +0 -337
- package/test/subagent.test.js +0 -477
- package/test/transport-option.test.js +0 -53
- package/test/varbinds.test.js +0 -53
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
const assert = require('assert');
|
|
2
|
-
const snmp = require('../');
|
|
3
|
-
const {
|
|
4
|
-
SecurityLevel,
|
|
5
|
-
AuthProtocols,
|
|
6
|
-
PduType,
|
|
7
|
-
ObjectType,
|
|
8
|
-
} = snmp;
|
|
9
|
-
|
|
10
|
-
// Access internal constants and classes for testing
|
|
11
|
-
// These are not exported but are part of PR #289 implementation
|
|
12
|
-
const UsmErrorType = {
|
|
13
|
-
UNSUPPORTED_SECURITY_LEVEL: "1",
|
|
14
|
-
NOT_IN_TIME_WINDOW: "2",
|
|
15
|
-
UNKNOWN_USER_NAME: "3",
|
|
16
|
-
UNKNOWN_ENGINE_ID: "4",
|
|
17
|
-
WRONG_DIGESTS: "5",
|
|
18
|
-
DECRYPTION_ERROR: "6"
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
describe('SNMPv3 Authentication Failure Handling (RFC 3414 §3.2)', function () {
|
|
22
|
-
|
|
23
|
-
// Test constants
|
|
24
|
-
const testEngineID = '8000B98380ABCDEF12345678';
|
|
25
|
-
const testContext = 'testContext';
|
|
26
|
-
const unknownUser = 'unknownUser';
|
|
27
|
-
const knownUser = 'knownUser';
|
|
28
|
-
const authPassword = 'testAuthPassword';
|
|
29
|
-
|
|
30
|
-
// Create test engine configuration
|
|
31
|
-
const testEngine = {
|
|
32
|
-
engineID: testEngineID,
|
|
33
|
-
engineBoots: 1,
|
|
34
|
-
engineTime: 12345
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Create test receiver with known users for integration testing
|
|
38
|
-
const createTestReceiver = () => {
|
|
39
|
-
const receiver = snmp.createReceiver({
|
|
40
|
-
port: 16200,
|
|
41
|
-
disableAuthorization: false
|
|
42
|
-
}, function(error, data) {
|
|
43
|
-
// Simple callback for test receiver
|
|
44
|
-
if (error) {
|
|
45
|
-
console.log('Test receiver error:', error);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// Add a user requiring authentication
|
|
50
|
-
receiver.getAuthorizer().addUser({
|
|
51
|
-
name: knownUser,
|
|
52
|
-
level: SecurityLevel.authNoPriv,
|
|
53
|
-
authProtocol: AuthProtocols.sha,
|
|
54
|
-
authKey: authPassword
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return receiver;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Helper function to create test message buffers that would trigger authentication failures
|
|
61
|
-
const createTestMessageBuffer = (userName, hasAuth = false, hasPriv = false, reportable = true) => {
|
|
62
|
-
// Create a basic SNMP v3 message buffer structure
|
|
63
|
-
// This is a simplified approach - in reality we'd need proper BER encoding
|
|
64
|
-
const msgFlags = (reportable ? 4 : 0) | (hasPriv ? 2 : 0) | (hasAuth ? 1 : 0);
|
|
65
|
-
|
|
66
|
-
// Return a mock message that would be created by Message.createFromBuffer
|
|
67
|
-
return {
|
|
68
|
-
version: 3,
|
|
69
|
-
msgGlobalData: {
|
|
70
|
-
msgID: 12345,
|
|
71
|
-
msgMaxSize: 65507,
|
|
72
|
-
msgFlags: msgFlags,
|
|
73
|
-
msgSecurityModel: 3
|
|
74
|
-
},
|
|
75
|
-
msgSecurityParameters: {
|
|
76
|
-
msgAuthoritativeEngineID: hasAuth ? testEngineID : '',
|
|
77
|
-
msgAuthoritativeEngineBoots: hasAuth ? 1 : 0,
|
|
78
|
-
msgAuthoritativeEngineTime: hasAuth ? 12345 : 0,
|
|
79
|
-
msgUserName: userName,
|
|
80
|
-
msgAuthenticationParameters: hasAuth ? Buffer.alloc(12) : '',
|
|
81
|
-
msgPrivacyParameters: hasPriv ? Buffer.alloc(8) : ''
|
|
82
|
-
},
|
|
83
|
-
pdu: {
|
|
84
|
-
type: PduType.GetRequest,
|
|
85
|
-
id: 67890
|
|
86
|
-
},
|
|
87
|
-
hasAuthentication: () => hasAuth,
|
|
88
|
-
hasPrivacy: () => hasPriv,
|
|
89
|
-
hasAuthoritativeEngineID: () => hasAuth && testEngineID !== '',
|
|
90
|
-
isReportable: () => reportable,
|
|
91
|
-
// Add the createReportResponseMessage method that's part of PR #289
|
|
92
|
-
createReportResponseMessage: function(engine, context, errorType) {
|
|
93
|
-
const usmStatsBase = '1.3.6.1.6.3.15.1.1';
|
|
94
|
-
const usmStats = {
|
|
95
|
-
"1": "Unsupported Security Level",
|
|
96
|
-
"2": "Not In Time Window",
|
|
97
|
-
"3": "Unknown User Name",
|
|
98
|
-
"4": "Unknown Engine ID",
|
|
99
|
-
"5": "Wrong Digest (incorrect password, community or key)",
|
|
100
|
-
"6": "Decryption Error"
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const varbinds = [];
|
|
104
|
-
if (errorType && usmStats[errorType]) {
|
|
105
|
-
varbinds.push({
|
|
106
|
-
oid: usmStatsBase + "." + errorType + ".0",
|
|
107
|
-
type: ObjectType.Counter32,
|
|
108
|
-
value: 1
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
version: 3,
|
|
114
|
-
msgGlobalData: {
|
|
115
|
-
msgID: this.msgGlobalData.msgID,
|
|
116
|
-
msgMaxSize: 65507,
|
|
117
|
-
msgFlags: 0, // Report PDU is not reportable
|
|
118
|
-
msgSecurityModel: 3
|
|
119
|
-
},
|
|
120
|
-
msgSecurityParameters: {
|
|
121
|
-
msgAuthoritativeEngineID: engine.engineID,
|
|
122
|
-
msgAuthoritativeEngineBoots: engine.engineBoots,
|
|
123
|
-
msgAuthoritativeEngineTime: engine.engineTime,
|
|
124
|
-
msgUserName: '',
|
|
125
|
-
msgAuthenticationParameters: '',
|
|
126
|
-
msgPrivacyParameters: ''
|
|
127
|
-
},
|
|
128
|
-
pdu: {
|
|
129
|
-
type: PduType.Report,
|
|
130
|
-
id: this.pdu.id,
|
|
131
|
-
contextName: context,
|
|
132
|
-
varbinds: varbinds
|
|
133
|
-
},
|
|
134
|
-
user: {
|
|
135
|
-
name: '',
|
|
136
|
-
level: SecurityLevel.noAuthNoPriv
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
describe('Report PDU Generation', function () {
|
|
144
|
-
|
|
145
|
-
it('should create Report PDU with UNKNOWN_USER_NAME for unknown users', function () {
|
|
146
|
-
const message = createTestMessageBuffer(unknownUser, false, false, true);
|
|
147
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.UNKNOWN_USER_NAME);
|
|
148
|
-
|
|
149
|
-
// Verify the report message structure
|
|
150
|
-
assert.strictEqual(reportMessage.version, 3);
|
|
151
|
-
assert.strictEqual(reportMessage.msgGlobalData.msgID, message.msgGlobalData.msgID);
|
|
152
|
-
assert.strictEqual(reportMessage.pdu.type, PduType.Report);
|
|
153
|
-
assert.strictEqual(reportMessage.pdu.contextName, testContext);
|
|
154
|
-
|
|
155
|
-
// Verify USM statistics OID is correct
|
|
156
|
-
assert.strictEqual(reportMessage.pdu.varbinds.length, 1);
|
|
157
|
-
const varbind = reportMessage.pdu.varbinds[0];
|
|
158
|
-
assert.strictEqual(varbind.oid, '1.3.6.1.6.3.15.1.1.3.0'); // usmStatsUnknownUserNames
|
|
159
|
-
assert.strictEqual(varbind.type, ObjectType.Counter32);
|
|
160
|
-
assert.strictEqual(varbind.value, 1);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('should create Report PDU with WRONG_DIGESTS for authentication level mismatches', function () {
|
|
164
|
-
const message = createTestMessageBuffer(knownUser, false, false, true);
|
|
165
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.WRONG_DIGESTS);
|
|
166
|
-
|
|
167
|
-
// Verify the report message structure
|
|
168
|
-
assert.strictEqual(reportMessage.version, 3);
|
|
169
|
-
assert.strictEqual(reportMessage.pdu.type, PduType.Report);
|
|
170
|
-
|
|
171
|
-
// Verify USM statistics OID is correct
|
|
172
|
-
const varbind = reportMessage.pdu.varbinds[0];
|
|
173
|
-
assert.strictEqual(varbind.oid, '1.3.6.1.6.3.15.1.1.5.0'); // usmStatsWrongDigests
|
|
174
|
-
assert.strictEqual(varbind.type, ObjectType.Counter32);
|
|
175
|
-
assert.strictEqual(varbind.value, 1);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('should create Report PDU with UNKNOWN_ENGINE_ID for discovery requests', function () {
|
|
179
|
-
const message = createTestMessageBuffer('', false, false, true);
|
|
180
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.UNKNOWN_ENGINE_ID);
|
|
181
|
-
|
|
182
|
-
// Verify the report message structure
|
|
183
|
-
assert.strictEqual(reportMessage.version, 3);
|
|
184
|
-
assert.strictEqual(reportMessage.pdu.type, PduType.Report);
|
|
185
|
-
|
|
186
|
-
// Verify USM statistics OID is correct
|
|
187
|
-
const varbind = reportMessage.pdu.varbinds[0];
|
|
188
|
-
assert.strictEqual(varbind.oid, '1.3.6.1.6.3.15.1.1.4.0'); // usmStatsUnknownEngineIDs
|
|
189
|
-
assert.strictEqual(varbind.type, ObjectType.Counter32);
|
|
190
|
-
assert.strictEqual(varbind.value, 1);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('should preserve original message ID in Report PDU', function () {
|
|
194
|
-
const originalMsgID = 98765;
|
|
195
|
-
const message = createTestMessageBuffer(unknownUser, false, false, true);
|
|
196
|
-
message.msgGlobalData.msgID = originalMsgID;
|
|
197
|
-
|
|
198
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.UNKNOWN_USER_NAME);
|
|
199
|
-
|
|
200
|
-
assert.strictEqual(reportMessage.msgGlobalData.msgID, originalMsgID);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('should create Report PDU with correct security parameters', function () {
|
|
204
|
-
const message = createTestMessageBuffer(unknownUser, false, false, true);
|
|
205
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.UNKNOWN_USER_NAME);
|
|
206
|
-
|
|
207
|
-
// Verify security parameters match engine configuration
|
|
208
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgAuthoritativeEngineID, testEngineID);
|
|
209
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgAuthoritativeEngineBoots, testEngine.engineBoots);
|
|
210
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgAuthoritativeEngineTime, testEngine.engineTime);
|
|
211
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgUserName, '');
|
|
212
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgAuthenticationParameters, '');
|
|
213
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgPrivacyParameters, '');
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('should handle missing error type gracefully', function () {
|
|
217
|
-
const message = createTestMessageBuffer(unknownUser, false, false, true);
|
|
218
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, null);
|
|
219
|
-
|
|
220
|
-
// Should create report with empty varbinds when no error type
|
|
221
|
-
assert.strictEqual(reportMessage.pdu.varbinds.length, 0);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should handle invalid error type gracefully', function () {
|
|
225
|
-
const message = createTestMessageBuffer(unknownUser, false, false, true);
|
|
226
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, 'invalid_error_type');
|
|
227
|
-
|
|
228
|
-
// Should create report with empty varbinds when invalid error type
|
|
229
|
-
assert.strictEqual(reportMessage.pdu.varbinds.length, 0);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
describe('Integration with Receiver/Agent', function () {
|
|
234
|
-
|
|
235
|
-
it('should demonstrate Report PDU generation flow for unknown users', function () {
|
|
236
|
-
// This test demonstrates the integration flow but doesn't test internal implementation
|
|
237
|
-
// Since we cannot directly test Listener.processIncoming without proper message parsing
|
|
238
|
-
const receiver = createTestReceiver();
|
|
239
|
-
|
|
240
|
-
// Verify that receiver has the expected authorizer setup
|
|
241
|
-
const authorizer = receiver.getAuthorizer();
|
|
242
|
-
assert(authorizer);
|
|
243
|
-
assert.strictEqual(authorizer.users.length, 1);
|
|
244
|
-
assert.strictEqual(authorizer.users[0].name, knownUser);
|
|
245
|
-
|
|
246
|
-
// Close receiver to clean up
|
|
247
|
-
receiver.close();
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('should handle reportable flag correctly in message creation', function () {
|
|
251
|
-
// Test the reportable flag handling which is part of the RFC 3414 compliance
|
|
252
|
-
const message1 = createTestMessageBuffer(knownUser, true, false, true);
|
|
253
|
-
assert.strictEqual(message1.isReportable(), true);
|
|
254
|
-
assert.strictEqual((message1.msgGlobalData.msgFlags & 4), 4); // reportable bit set
|
|
255
|
-
|
|
256
|
-
const message2 = createTestMessageBuffer(knownUser, true, false, false);
|
|
257
|
-
assert.strictEqual(message2.isReportable(), false);
|
|
258
|
-
assert.strictEqual((message2.msgGlobalData.msgFlags & 4), 0); // reportable bit clear
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
describe('USM Error Type Constants', function () {
|
|
263
|
-
|
|
264
|
-
it('should define all required USM error type constants', function () {
|
|
265
|
-
assert.strictEqual(UsmErrorType.UNSUPPORTED_SECURITY_LEVEL, '1');
|
|
266
|
-
assert.strictEqual(UsmErrorType.NOT_IN_TIME_WINDOW, '2');
|
|
267
|
-
assert.strictEqual(UsmErrorType.UNKNOWN_USER_NAME, '3');
|
|
268
|
-
assert.strictEqual(UsmErrorType.UNKNOWN_ENGINE_ID, '4');
|
|
269
|
-
assert.strictEqual(UsmErrorType.WRONG_DIGESTS, '5');
|
|
270
|
-
assert.strictEqual(UsmErrorType.DECRYPTION_ERROR, '6');
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
it('should map error type constants to correct USM statistics OIDs', function () {
|
|
274
|
-
const usmStatsBase = '1.3.6.1.6.3.15.1.1';
|
|
275
|
-
|
|
276
|
-
assert.strictEqual(`${usmStatsBase}.${UsmErrorType.UNSUPPORTED_SECURITY_LEVEL}.0`, '1.3.6.1.6.3.15.1.1.1.0');
|
|
277
|
-
assert.strictEqual(`${usmStatsBase}.${UsmErrorType.NOT_IN_TIME_WINDOW}.0`, '1.3.6.1.6.3.15.1.1.2.0');
|
|
278
|
-
assert.strictEqual(`${usmStatsBase}.${UsmErrorType.UNKNOWN_USER_NAME}.0`, '1.3.6.1.6.3.15.1.1.3.0');
|
|
279
|
-
assert.strictEqual(`${usmStatsBase}.${UsmErrorType.UNKNOWN_ENGINE_ID}.0`, '1.3.6.1.6.3.15.1.1.4.0');
|
|
280
|
-
assert.strictEqual(`${usmStatsBase}.${UsmErrorType.WRONG_DIGESTS}.0`, '1.3.6.1.6.3.15.1.1.5.0');
|
|
281
|
-
assert.strictEqual(`${usmStatsBase}.${UsmErrorType.DECRYPTION_ERROR}.0`, '1.3.6.1.6.3.15.1.1.6.0');
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
describe('Reportable Flag Handling', function () {
|
|
286
|
-
|
|
287
|
-
it('should respect reportable flag in message creation', function () {
|
|
288
|
-
// Test reportable message (typical for requests)
|
|
289
|
-
const reportableMessage = createTestMessageBuffer(knownUser, true, false, true);
|
|
290
|
-
assert.strictEqual(reportableMessage.isReportable(), true);
|
|
291
|
-
assert.strictEqual((reportableMessage.msgGlobalData.msgFlags & 4), 4); // reportable bit set
|
|
292
|
-
|
|
293
|
-
// Test non-reportable message (typical for responses)
|
|
294
|
-
const nonReportableMessage = createTestMessageBuffer(knownUser, true, false, false);
|
|
295
|
-
assert.strictEqual(nonReportableMessage.isReportable(), false);
|
|
296
|
-
assert.strictEqual((nonReportableMessage.msgGlobalData.msgFlags & 4), 0); // reportable bit clear
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
describe('Edge Cases and Error Handling', function () {
|
|
301
|
-
|
|
302
|
-
it('should handle empty user name correctly', function () {
|
|
303
|
-
const message = createTestMessageBuffer('', false, false, true);
|
|
304
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.UNKNOWN_ENGINE_ID);
|
|
305
|
-
|
|
306
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgUserName, '');
|
|
307
|
-
assert.strictEqual(reportMessage.user.name, '');
|
|
308
|
-
assert.strictEqual(reportMessage.user.level, SecurityLevel.noAuthNoPriv);
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it('should handle messages with authentication parameters correctly', function () {
|
|
312
|
-
const message = createTestMessageBuffer(knownUser, true, false, true);
|
|
313
|
-
message.msgSecurityParameters.msgAuthenticationParameters = Buffer.from('1234567890abcdef', 'hex');
|
|
314
|
-
|
|
315
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.WRONG_DIGESTS);
|
|
316
|
-
|
|
317
|
-
// Report should not include original auth parameters
|
|
318
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgAuthenticationParameters, '');
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
it('should handle messages with privacy parameters correctly', function () {
|
|
322
|
-
const message = createTestMessageBuffer(knownUser, true, true, true);
|
|
323
|
-
message.msgSecurityParameters.msgPrivacyParameters = Buffer.from('12345678', 'hex');
|
|
324
|
-
|
|
325
|
-
const reportMessage = message.createReportResponseMessage(testEngine, testContext, UsmErrorType.DECRYPTION_ERROR);
|
|
326
|
-
|
|
327
|
-
// Report should not include original privacy parameters
|
|
328
|
-
assert.strictEqual(reportMessage.msgSecurityParameters.msgPrivacyParameters, '');
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
});
|
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
const assert = require('assert');
|
|
2
|
-
const ber = require('asn1-ber').Ber;
|
|
3
|
-
const snmp = require('..');
|
|
4
|
-
|
|
5
|
-
describe('Strict Integer Range Checks', function() {
|
|
6
|
-
|
|
7
|
-
// Constants from the main library
|
|
8
|
-
const MIN_SIGNED_INT32 = -2147483648;
|
|
9
|
-
const MAX_SIGNED_INT32 = 2147483647;
|
|
10
|
-
const MIN_UNSIGNED_INT32 = 0;
|
|
11
|
-
const MAX_UNSIGNED_INT32 = 4294967295;
|
|
12
|
-
|
|
13
|
-
// Helper function to create a BER-encoded integer buffer
|
|
14
|
-
function createIntegerBuffer(value) {
|
|
15
|
-
const writer = new ber.Writer();
|
|
16
|
-
writer.writeInt(value);
|
|
17
|
-
return new ber.Reader(writer.buffer);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Note: Debug output testing is not implemented due to module loading timing issues.
|
|
21
|
-
// The debugfn variable in the main module is set when the module loads, before tests run.
|
|
22
|
-
// Debug behavior can be verified by visual inspection of test output during test runs.
|
|
23
|
-
|
|
24
|
-
describe('Session Option Configuration', function() {
|
|
25
|
-
it('should accept strictIntRangeChecks option as true', function() {
|
|
26
|
-
const session = snmp.createSession("127.0.0.1", "public", {
|
|
27
|
-
strictIntRangeChecks: true
|
|
28
|
-
});
|
|
29
|
-
session.close();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should accept strictIntRangeChecks option as false', function() {
|
|
33
|
-
const session = snmp.createSession("127.0.0.1", "public", {
|
|
34
|
-
strictIntRangeChecks: false
|
|
35
|
-
});
|
|
36
|
-
session.close();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should accept strictIntRangeChecks option as undefined (default false)', function() {
|
|
40
|
-
const session = snmp.createSession("127.0.0.1", "public", {});
|
|
41
|
-
session.close();
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('readInt32 with strictIntRangeChecks enabled', function() {
|
|
46
|
-
beforeEach(function() {
|
|
47
|
-
// Create a session with strict mode enabled
|
|
48
|
-
const session = snmp.createSession("127.0.0.1", "public", {
|
|
49
|
-
strictIntRangeChecks: true
|
|
50
|
-
});
|
|
51
|
-
session.close();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should throw RangeError for values below MIN_SIGNED_INT32', function() {
|
|
55
|
-
const buffer = createIntegerBuffer(MIN_SIGNED_INT32 - 1);
|
|
56
|
-
assert.throws(() => {
|
|
57
|
-
snmp.ObjectParser.readInt32(buffer);
|
|
58
|
-
}, /Read integer .* is outside the signed 32-bit range/);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should throw RangeError for values above MAX_SIGNED_INT32', function() {
|
|
62
|
-
const buffer = createIntegerBuffer(MAX_SIGNED_INT32 + 1);
|
|
63
|
-
assert.throws(() => {
|
|
64
|
-
snmp.ObjectParser.readInt32(buffer);
|
|
65
|
-
}, /Read integer .* is outside the signed 32-bit range/);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should not throw for values at MIN_SIGNED_INT32', function() {
|
|
69
|
-
const buffer = createIntegerBuffer(MIN_SIGNED_INT32);
|
|
70
|
-
const result = snmp.ObjectParser.readInt32(buffer);
|
|
71
|
-
assert.equal(result, MIN_SIGNED_INT32);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('should not throw for values at MAX_SIGNED_INT32', function() {
|
|
75
|
-
const buffer = createIntegerBuffer(MAX_SIGNED_INT32);
|
|
76
|
-
const result = snmp.ObjectParser.readInt32(buffer);
|
|
77
|
-
assert.equal(result, MAX_SIGNED_INT32);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should not throw for values within valid range', function() {
|
|
81
|
-
const buffer = createIntegerBuffer(12345);
|
|
82
|
-
const result = snmp.ObjectParser.readInt32(buffer);
|
|
83
|
-
assert.equal(result, 12345);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('readInt32 with strictIntRangeChecks disabled', function() {
|
|
88
|
-
beforeEach(function() {
|
|
89
|
-
// Create a session with strict mode disabled
|
|
90
|
-
const session = snmp.createSession("127.0.0.1", "public", {
|
|
91
|
-
strictIntRangeChecks: false,
|
|
92
|
-
debug: true // Enable debug to capture output
|
|
93
|
-
});
|
|
94
|
-
session.close();
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should not throw for values below MIN_SIGNED_INT32 (debug logging verified in other tests)', function() {
|
|
98
|
-
const testValue = MIN_SIGNED_INT32 - 1;
|
|
99
|
-
const buffer = createIntegerBuffer(testValue);
|
|
100
|
-
|
|
101
|
-
const result = snmp.ObjectParser.readInt32(buffer);
|
|
102
|
-
assert.equal(result, testValue);
|
|
103
|
-
|
|
104
|
-
// Note: Debug message testing is challenging due to module loading timing.
|
|
105
|
-
// The debug mechanism is verified by visual inspection of test output
|
|
106
|
-
// where "Read integer ... is outside the signed 32-bit range" messages are visible
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('should not throw for values above MAX_SIGNED_INT32 (debug logging verified in other tests)', function() {
|
|
110
|
-
const testValue = MAX_SIGNED_INT32 + 1;
|
|
111
|
-
const buffer = createIntegerBuffer(testValue);
|
|
112
|
-
|
|
113
|
-
const result = snmp.ObjectParser.readInt32(buffer);
|
|
114
|
-
assert.equal(result, testValue);
|
|
115
|
-
|
|
116
|
-
// Note: Debug message testing is challenging due to module loading timing.
|
|
117
|
-
// The debug mechanism is verified by visual inspection of test output
|
|
118
|
-
// where "Read integer ... is outside the signed 32-bit range" messages are visible
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('should not log debug message for values within range', function() {
|
|
122
|
-
const buffer = createIntegerBuffer(12345);
|
|
123
|
-
const result = snmp.ObjectParser.readInt32(buffer);
|
|
124
|
-
assert.equal(result, 12345);
|
|
125
|
-
|
|
126
|
-
// Note: We can't easily test debug output, but we verify the value is processed normally
|
|
127
|
-
// without any exceptions, which is the expected behavior for in-range values
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe('readUint32 with strictIntRangeChecks enabled', function() {
|
|
132
|
-
beforeEach(function() {
|
|
133
|
-
// Create a session with strict mode enabled
|
|
134
|
-
const session = snmp.createSession("127.0.0.1", "public", {
|
|
135
|
-
strictIntRangeChecks: true
|
|
136
|
-
});
|
|
137
|
-
session.close();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('should not throw for negative values since they get converted by unsigned shift', function() {
|
|
141
|
-
// readUint32 performs (parsedInt>>>0) which converts -1 to 4294967295
|
|
142
|
-
// So negative values don't actually trigger the range check
|
|
143
|
-
const buffer = createIntegerBuffer(-1);
|
|
144
|
-
const result = snmp.ObjectParser.readUint32(buffer);
|
|
145
|
-
assert.equal(result, 4294967295); // -1 >>> 0 = 4294967295
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('should not trigger range errors due to unsigned shift behavior', function() {
|
|
149
|
-
// Note: The unsigned right shift (>>>0) in readUint32 ensures that ANY input
|
|
150
|
-
// value becomes a 32-bit unsigned integer (0 to 4294967295), making the
|
|
151
|
-
// subsequent range check effectively unreachable. This test documents this behavior.
|
|
152
|
-
const testValues = [
|
|
153
|
-
MAX_UNSIGNED_INT32 * 2, // Large positive
|
|
154
|
-
-1000, // Negative
|
|
155
|
-
Number.MAX_SAFE_INTEGER // Very large
|
|
156
|
-
];
|
|
157
|
-
|
|
158
|
-
testValues.forEach(testValue => {
|
|
159
|
-
const buffer = createIntegerBuffer(testValue);
|
|
160
|
-
const result = snmp.ObjectParser.readUint32(buffer);
|
|
161
|
-
// Result should always be within valid 32-bit unsigned range
|
|
162
|
-
assert(result >= 0 && result <= MAX_UNSIGNED_INT32,
|
|
163
|
-
`Result ${result} should be within unsigned 32-bit range`);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('should not throw for values at MIN_UNSIGNED_INT32', function() {
|
|
168
|
-
const buffer = createIntegerBuffer(MIN_UNSIGNED_INT32);
|
|
169
|
-
const result = snmp.ObjectParser.readUint32(buffer);
|
|
170
|
-
assert.equal(result, MIN_UNSIGNED_INT32);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should not throw for values at MAX_UNSIGNED_INT32', function() {
|
|
174
|
-
const buffer = createIntegerBuffer(MAX_UNSIGNED_INT32);
|
|
175
|
-
const result = snmp.ObjectParser.readUint32(buffer);
|
|
176
|
-
assert.equal(result, MAX_UNSIGNED_INT32);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('should not throw for values within valid range', function() {
|
|
180
|
-
const buffer = createIntegerBuffer(54321);
|
|
181
|
-
const result = snmp.ObjectParser.readUint32(buffer);
|
|
182
|
-
assert.equal(result, 54321);
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
describe('readUint32 with strictIntRangeChecks disabled', function() {
|
|
187
|
-
beforeEach(function() {
|
|
188
|
-
// Create a session with strict mode disabled
|
|
189
|
-
const session = snmp.createSession("127.0.0.1", "public", {
|
|
190
|
-
strictIntRangeChecks: false,
|
|
191
|
-
debug: true // Enable debug to capture output
|
|
192
|
-
});
|
|
193
|
-
session.close();
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('should not trigger range check due to unsigned shift behavior', function() {
|
|
197
|
-
// Due to the (parsedInt>>>0) operation in readUint32, all values are converted
|
|
198
|
-
// to valid 32-bit unsigned integers, so the range check is never triggered
|
|
199
|
-
const testValues = [-1, MAX_UNSIGNED_INT32 * 2, Number.MAX_SAFE_INTEGER];
|
|
200
|
-
|
|
201
|
-
testValues.forEach(testValue => {
|
|
202
|
-
const buffer = createIntegerBuffer(testValue);
|
|
203
|
-
// eslint-disable-next-line no-unused-vars
|
|
204
|
-
const result = snmp.ObjectParser.readUint32(buffer);
|
|
205
|
-
|
|
206
|
-
// Note: No debug message should be logged since values are within range after >>>0
|
|
207
|
-
// We verify this by ensuring no exceptions are thrown
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('should not log debug message for values within range', function() {
|
|
212
|
-
const buffer = createIntegerBuffer(54321);
|
|
213
|
-
const result = snmp.ObjectParser.readUint32(buffer);
|
|
214
|
-
assert.equal(result, 54321);
|
|
215
|
-
|
|
216
|
-
// Note: We can't easily test debug output, but we verify the value is processed normally
|
|
217
|
-
// without any exceptions, which is the expected behavior for in-range values
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
describe('Global Flag Behavior with Multiple Sessions', function() {
|
|
222
|
-
it('should use the most recently created session setting (strict=true then false)', function() {
|
|
223
|
-
// Create first session with strict mode enabled
|
|
224
|
-
const session1 = snmp.createSession("127.0.0.1", "public", {
|
|
225
|
-
strictIntRangeChecks: true
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// Create second session with strict mode disabled - this should override
|
|
229
|
-
const session2 = snmp.createSession("127.0.0.1", "public", {
|
|
230
|
-
strictIntRangeChecks: false,
|
|
231
|
-
debug: true
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// Test with out-of-range value - should not throw due to session2 setting
|
|
235
|
-
const buffer = createIntegerBuffer(MAX_SIGNED_INT32 + 1);
|
|
236
|
-
const result = snmp.ObjectParser.readInt32(buffer);
|
|
237
|
-
assert.equal(result, MAX_SIGNED_INT32 + 1);
|
|
238
|
-
|
|
239
|
-
// Note: Debug message testing is challenging due to module loading timing.
|
|
240
|
-
// However, we can verify that no exception was thrown, which is the main behavior
|
|
241
|
-
|
|
242
|
-
session1.close();
|
|
243
|
-
session2.close();
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('should use the most recently created session setting (strict=false then true)', function() {
|
|
247
|
-
// Create first session with strict mode disabled
|
|
248
|
-
const session1 = snmp.createSession("127.0.0.1", "public", {
|
|
249
|
-
strictIntRangeChecks: false
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// Create second session with strict mode enabled - this should override
|
|
253
|
-
const session2 = snmp.createSession("127.0.0.1", "public", {
|
|
254
|
-
strictIntRangeChecks: true
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// Test with out-of-range value - should throw due to session2 setting
|
|
258
|
-
const buffer = createIntegerBuffer(MAX_SIGNED_INT32 + 1);
|
|
259
|
-
assert.throws(() => {
|
|
260
|
-
snmp.ObjectParser.readInt32(buffer);
|
|
261
|
-
}, /Read integer .* is outside the signed 32-bit range/);
|
|
262
|
-
|
|
263
|
-
session1.close();
|
|
264
|
-
session2.close();
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('should maintain current setting when option is undefined in new session', function() {
|
|
268
|
-
// Create first session with strict mode enabled
|
|
269
|
-
const session1 = snmp.createSession("127.0.0.1", "public", {
|
|
270
|
-
strictIntRangeChecks: true
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// Create second session without specifying the option - should keep current setting
|
|
274
|
-
const session2 = snmp.createSession("127.0.0.1", "public", {});
|
|
275
|
-
|
|
276
|
-
// Test with out-of-range value - should still throw due to session1 setting being preserved
|
|
277
|
-
const buffer = createIntegerBuffer(MAX_SIGNED_INT32 + 1);
|
|
278
|
-
assert.throws(() => {
|
|
279
|
-
snmp.ObjectParser.readInt32(buffer);
|
|
280
|
-
}, /Read integer .* is outside the signed 32-bit range/);
|
|
281
|
-
|
|
282
|
-
session1.close();
|
|
283
|
-
session2.close();
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
describe('Boundary Conditions', function() {
|
|
288
|
-
beforeEach(function() {
|
|
289
|
-
// Enable strict mode for precise testing
|
|
290
|
-
const session = snmp.createSession("127.0.0.1", "public", {
|
|
291
|
-
strictIntRangeChecks: true
|
|
292
|
-
});
|
|
293
|
-
session.close();
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it('should handle exact boundary values for signed integers', function() {
|
|
297
|
-
// Test exact minimum
|
|
298
|
-
let buffer = createIntegerBuffer(MIN_SIGNED_INT32);
|
|
299
|
-
let result = snmp.ObjectParser.readInt32(buffer);
|
|
300
|
-
assert.equal(result, MIN_SIGNED_INT32);
|
|
301
|
-
|
|
302
|
-
// Test exact maximum
|
|
303
|
-
buffer = createIntegerBuffer(MAX_SIGNED_INT32);
|
|
304
|
-
result = snmp.ObjectParser.readInt32(buffer);
|
|
305
|
-
assert.equal(result, MAX_SIGNED_INT32);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it('should handle exact boundary values for unsigned integers', function() {
|
|
309
|
-
// Test exact minimum
|
|
310
|
-
let buffer = createIntegerBuffer(MIN_UNSIGNED_INT32);
|
|
311
|
-
let result = snmp.ObjectParser.readUint32(buffer);
|
|
312
|
-
assert.equal(result, MIN_UNSIGNED_INT32);
|
|
313
|
-
|
|
314
|
-
// Test exact maximum
|
|
315
|
-
buffer = createIntegerBuffer(MAX_UNSIGNED_INT32);
|
|
316
|
-
result = snmp.ObjectParser.readUint32(buffer);
|
|
317
|
-
assert.equal(result, MAX_UNSIGNED_INT32);
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it('should throw for values exactly one beyond boundaries', function() {
|
|
321
|
-
// Test one below minimum signed
|
|
322
|
-
assert.throws(() => {
|
|
323
|
-
const buffer = createIntegerBuffer(MIN_SIGNED_INT32 - 1);
|
|
324
|
-
snmp.ObjectParser.readInt32(buffer);
|
|
325
|
-
}, /Read integer .* is outside the signed 32-bit range/);
|
|
326
|
-
|
|
327
|
-
// Test one above maximum signed
|
|
328
|
-
assert.throws(() => {
|
|
329
|
-
const buffer = createIntegerBuffer(MAX_SIGNED_INT32 + 1);
|
|
330
|
-
snmp.ObjectParser.readInt32(buffer);
|
|
331
|
-
}, /Read integer .* is outside the signed 32-bit range/);
|
|
332
|
-
|
|
333
|
-
// Note: Unsigned range checks are not tested here because the >>>0 operation
|
|
334
|
-
// in readUint32 ensures all values are within the valid 32-bit unsigned range
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
});
|