• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lextudio / sharpsnmplib / 11823966615

13 Nov 2024 06:58PM UTC coverage: 49.626% (-3.4%) from 53.042%
11823966615

push

github

lextm
Removed .NET 6.

819 of 1881 branches covered (43.54%)

Branch coverage included in aggregate %.

2232 of 4267 relevant lines covered (52.31%)

15136.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/SharpSnmpLib/Messaging/Net6Messenger.cs
1
// Messenger class.
2
// Copyright (C) 2009-2010 Lex Li
3
// 
4
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
5
// software and associated documentation files (the "Software"), to deal in the Software
6
// without restriction, including without limitation the rights to use, copy, modify, merge,
7
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
8
// to whom the Software is furnished to do so, subject to the following conditions:
9
// 
10
// The above copyright notice and this permission notice shall be included in all copies or
11
// substantial portions of the Software.
12
// 
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
15
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
16
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
// DEALINGS IN THE SOFTWARE.
19

20
/*
21
 * Created by SharpDevelop.
22
 * User: lextm
23
 * Date: 2009/3/29
24
 * Time: 17:52
25
 * 
26
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
27
 */
28
#if NET6_0_OR_GREATER
29
using System;
30
using System.Collections.Generic;
31
using System.Diagnostics.CodeAnalysis;
32
using System.Globalization;
33
using System.Net;
34
using Lextm.SharpSnmpLib.Security;
35
using System.Threading;
36
using System.Threading.Tasks;
37

38
namespace Lextm.SharpSnmpLib.Messaging
39
{
40

41
    /// <summary>
42
    /// Messenger class contains all static helper methods you need to send out SNMP messages.
43
    /// Static methods in Manager or Agent class will be removed in the future.
44
    /// </summary>
45
    /// <remarks>
46
    /// SNMP v3 is not supported in many methods of this class. Please use <see cref="ISnmpMessage" /> derived classes directly
47
    /// if you want to do v3 operations.
48
    /// </remarks>
49
    public static partial class Messenger
50
    {
51
        #region async methods
52

53
        /// <summary>
54
        /// Gets a list of variable binds.
55
        /// </summary>
56
        /// <param name="version">Protocol version.</param>
57
        /// <param name="endpoint">Endpoint.</param>
58
        /// <param name="community">Community name.</param>
59
        /// <param name="variables">Variable binds.</param>
60
        /// <param name="token">The cancellation token.</param>
61
        /// <returns></returns>
62
        [RequiresUnreferencedCode("GetAsync is incompatible with trimming.")]
63
        public static async Task<IList<Variable>> GetAsync(VersionCode version, IPEndPoint endpoint, OctetString community, IList<Variable> variables, CancellationToken token)
64
        {
65
            if (endpoint == null)
×
66
            {
67
                throw new ArgumentNullException(nameof(endpoint));
×
68
            }
69

70
            if (community == null)
×
71
            {
72
                throw new ArgumentNullException(nameof(community));
×
73
            }
74

75
            if (variables == null)
×
76
            {
77
                throw new ArgumentNullException(nameof(variables));
×
78
            }
79

80
            if (version == VersionCode.V3)
×
81
            {
82
                throw new NotSupportedException("SNMP v3 is not supported");
×
83
            }
84

85
            var message = new GetRequestMessage(Messenger.NextRequestId, version, community, variables);
×
86
            var response = await message.GetResponseAsync(endpoint, token).ConfigureAwait(false);
×
87
            var pdu = response.Pdu();
×
88
            if (pdu.ErrorStatus.ToInt32() != 0)
×
89
            {
90
                throw ErrorException.Create(
×
91
                    "error in response",
×
92
                    endpoint.Address,
×
93
                    response);
×
94
            }
95

96
            return pdu.Variables;
×
97
        }
×
98

99
        /// <summary>
100
        /// Sets a list of variable binds.
101
        /// </summary>
102
        /// <param name="version">Protocol version.</param>
103
        /// <param name="endpoint">Endpoint.</param>
104
        /// <param name="community">Community name.</param>
105
        /// <param name="variables">Variable binds.</param>
106
        /// <param name="token">The cancellation token.</param>
107
        /// <returns></returns>
108
        [RequiresUnreferencedCode("SetAsync is incompatible with trimming.")]
109
        public static async Task<IList<Variable>> SetAsync(VersionCode version, IPEndPoint endpoint, OctetString community, IList<Variable> variables, CancellationToken token)
110
        {
111
            if (endpoint == null)
×
112
            {
113
                throw new ArgumentNullException(nameof(endpoint));
×
114
            }
115

116
            if (community == null)
×
117
            {
118
                throw new ArgumentNullException(nameof(community));
×
119
            }
120

121
            if (variables == null)
×
122
            {
123
                throw new ArgumentNullException(nameof(variables));
×
124
            }
125

126
            if (version == VersionCode.V3)
×
127
            {
128
                throw new NotSupportedException("SNMP v3 is not supported");
×
129
            }
130

131
            var message = new SetRequestMessage(Messenger.NextRequestId, version, community, variables);
×
132
            var response = await message.GetResponseAsync(endpoint, token).ConfigureAwait(false);
×
133
            var pdu = response.Pdu();
×
134
            if (pdu.ErrorStatus.ToInt32() != 0)
×
135
            {
136
                throw ErrorException.Create(
×
137
                    "error in response",
×
138
                    endpoint.Address,
×
139
                    response);
×
140
            }
141

142
            return pdu.Variables;
×
143
        }
×
144

145
        /// <summary>
146
        /// Walks (based on GET NEXT).
147
        /// </summary>
148
        /// <param name="version">Protocol version.</param>
149
        /// <param name="endpoint">Endpoint.</param>
150
        /// <param name="community">Community name.</param>
151
        /// <param name="table">OID.</param>
152
        /// <param name="list">A list to hold the results.</param>
153
        /// <param name="mode">Walk mode.</param>
154
        /// <param name="token">The cancellation token.</param>
155
        /// <returns>
156
        /// Returns row count if the OID is a table. Otherwise this value is meaningless.
157
        /// </returns>
158
        /// <remarks>This method only supports SNMP v1 and v2c.</remarks>
159
        [RequiresUnreferencedCode("WalkAsync is incompatible with trimming.")]
160
        public static async Task<int> WalkAsync(VersionCode version, IPEndPoint endpoint, OctetString community, ObjectIdentifier table, IList<Variable> list, WalkMode mode, CancellationToken token)
161
        {
162
            if (list == null)
×
163
            {
164
                throw new ArgumentNullException(nameof(list));
×
165
            }
166

167
            var result = 0;
×
168
            var tableV = new Variable(table);
×
169
            var next = tableV;
×
170
            var rowMask = string.Format(CultureInfo.InvariantCulture, "{0}.1.1.", table);
×
171
            var subTreeMask = string.Format(CultureInfo.InvariantCulture, "{0}.", table);
×
172
            Tuple<bool, Variable?> data = new(false, next);
×
173
            do
174
            {
175
                var seed = data.Item2;
×
176

177
                if (version == VersionCode.V2 && seed?.Data.TypeCode == SnmpType.EndOfMibView)
×
178
                {
179
                    break;
180
                }
181

182
                if (seed == tableV)
×
183
                {
184
                    data = await HasNextAsync(version, endpoint, community, seed, token).ConfigureAwait(false);
×
185
                    continue;
×
186
                }
187

188
                if (seed == null)
×
189
                {
190
                    break;
191
                }
192

193
                if (mode == WalkMode.WithinSubtree && !seed.Id.ToString().StartsWith(subTreeMask, StringComparison.Ordinal))
×
194
                {
195
                    // not in sub tree
196
                    break;
197
                }
198

199
                list.Add(seed);
×
200
                if (seed.Id.ToString().StartsWith(rowMask, StringComparison.Ordinal))
×
201
                {
202
                    result++;
×
203
                }
204

205
                data = await HasNextAsync(version, endpoint, community, seed, token).ConfigureAwait(false);
×
206
            }
207
            while (data.Item1);
×
208
            return result;
×
209
        }
×
210

211
        /// <summary>
212
        /// Determines whether the specified seed has next item.
213
        /// </summary>
214
        /// <param name="version">The version.</param>
215
        /// <param name="endpoint">The endpoint.</param>
216
        /// <param name="community">The community.</param>
217
        /// <param name="seed">The seed.</param>
218
        /// <param name="token">The cancellation token.</param>
219
        /// <returns>
220
        ///     <c>true</c> if the specified seed has next item; otherwise, <c>false</c>.
221
        /// </returns>
222
        /// <remarks>This method only supports SNMP v1 and v2c.</remarks>
223
        [RequiresUnreferencedCode("HasNextAsync is incompatible with trimming.")]
224
        private static async Task<Tuple<bool, Variable?>> HasNextAsync(VersionCode version, IPEndPoint endpoint, OctetString community, Variable seed, CancellationToken token)
225
        {
226
            if (seed == null)
×
227
            {
228
                throw new ArgumentNullException(nameof(seed));
×
229
            }
230

231
            var variables = new List<Variable> { new(seed.Id) };
×
232
            var message = new GetNextRequestMessage(
×
233
                NextRequestId,
×
234
                version,
×
235
                community,
×
236
                variables);
×
237

238
            var response = await message.GetResponseAsync(endpoint, token).ConfigureAwait(false);
×
239
            var pdu = response.Pdu();
×
240
            var errorFound = pdu.ErrorStatus.ToErrorCode() == ErrorCode.NoSuchName;
×
241
            return new Tuple<bool, Variable?>(!errorFound, errorFound ? null : pdu.Variables[0]);
×
242
        }
×
243

244
        /// <summary>
245
        /// Walks (based on GET BULK).
246
        /// </summary>
247
        /// <param name="version">Protocol version.</param>
248
        /// <param name="endpoint">Endpoint.</param>
249
        /// <param name="community">Community name (v2c) or user name (v3).</param>
250
        /// <param name="contextName">Context name.</param>
251
        /// <param name="table">OID.</param>
252
        /// <param name="list">A list to hold the results.</param>
253
        /// <param name="maxRepetitions">The max repetitions.</param>
254
        /// <param name="mode">Walk mode.</param>
255
        /// <param name="privacy">The privacy provider.</param>
256
        /// <param name="report">The report.</param>
257
        /// <param name="token">The cancellation token.</param>
258
        /// <returns>Returns row count if the OID is a table. Otherwise this value is meaningless.</returns>
259
        /// <remarks>This method only supports SNMP v2c and v3.</remarks>
260
        [RequiresUnreferencedCode("BulkWalkAsync is incompatible with trimming.")]
261
        public static async Task<int> BulkWalkAsync(VersionCode version, IPEndPoint endpoint, OctetString community, OctetString contextName, ObjectIdentifier table, IList<Variable> list, int maxRepetitions, WalkMode mode, IPrivacyProvider privacy, ISnmpMessage report, CancellationToken token)
262
        {
263
            if (list == null)
×
264
            {
265
                throw new ArgumentNullException(nameof(list));
×
266
            }
267

268
            var tableV = new Variable(table);
×
269
            var seed = tableV;
×
270
            var result = 0;
×
271
            var message = report;
×
272
            var data = await BulkHasNextAsync(version, endpoint, community, contextName, seed, maxRepetitions, privacy, message, token).ConfigureAwait(false);
×
273
            var next = data.Item2;
×
274
            message = data.Item3;
×
275
            while (data.Item1)
×
276
            {
277
                var subTreeMask = string.Format(CultureInfo.InvariantCulture, "{0}.", table);
×
278
                var rowMask = string.Format(CultureInfo.InvariantCulture, "{0}.1.1.", table);
×
279
                foreach (var v in next)
×
280
                {
281
                    var id = v.Id.ToString();
×
282
                    if (v.Data.TypeCode == SnmpType.EndOfMibView)
×
283
                    {
284
                        goto end;
×
285
                    }
286

287
                    if (mode == WalkMode.WithinSubtree && !id.StartsWith(subTreeMask, StringComparison.Ordinal))
×
288
                    {
289
                        // not in sub tree
290
                        goto end;
×
291
                    }
292

293
                    list.Add(v);
×
294
                    if (id.StartsWith(rowMask, StringComparison.Ordinal))
×
295
                    {
296
                        result++;
×
297
                    }
298
                }
299

300
                seed = next[next.Count - 1];
×
301
                data = await BulkHasNextAsync(version, endpoint, community, contextName, seed, maxRepetitions, privacy, message, token).ConfigureAwait(false);
×
302
                next = data.Item2;
×
303
                message = data.Item3;
×
304
            }
305

306
        end:
307
            return result;
×
308
        }
×
309

310
        /// <summary>
311
        /// Sends a TRAP v1 message.
312
        /// </summary>
313
        /// <param name="receiver">Receiver.</param>
314
        /// <param name="agent">Agent.</param>
315
        /// <param name="community">Community name.</param>
316
        /// <param name="enterprise">Enterprise OID.</param>
317
        /// <param name="generic">Generic code.</param>
318
        /// <param name="specific">Specific code.</param>
319
        /// <param name="timestamp">Timestamp.</param>
320
        /// <param name="variables">Variable bindings.</param>
321
        /// <param name="token">The cancellation token.</param>
322
        /// <remarks>This method only supports SNMP v1.</remarks>
323
        [CLSCompliant(false)]
324
        public static async Task SendTrapV1Async(EndPoint receiver, IPAddress agent, OctetString community, ObjectIdentifier enterprise, GenericCode generic, int specific, uint timestamp, IList<Variable> variables, CancellationToken token)
325
        {
326
            var message = new TrapV1Message(VersionCode.V1, agent, community, enterprise, generic, specific, timestamp, variables);
×
327
            await message.SendAsync(receiver, token).ConfigureAwait(false);
×
328
        }
×
329

330
        /// <summary>
331
        /// Sends TRAP v2 message.
332
        /// </summary>
333
        /// <param name="version">Protocol version.</param>
334
        /// <param name="receiver">Receiver.</param>
335
        /// <param name="community">Community name.</param>
336
        /// <param name="enterprise">Enterprise OID.</param>
337
        /// <param name="timestamp">Timestamp.</param>
338
        /// <param name="variables">Variable bindings.</param>
339
        /// <param name="requestId">Request ID.</param>
340
        /// <param name="token">The cancellation token.</param>
341
        /// <remarks>This method only supports SNMP v2c.</remarks>
342
        [CLSCompliant(false)]
343
        public static async Task SendTrapV2Async(int requestId, VersionCode version, EndPoint receiver, OctetString community, ObjectIdentifier enterprise, uint timestamp, IList<Variable> variables, CancellationToken token)
344
        {
345
            if (version != VersionCode.V2)
×
346
            {
347
                throw new NotSupportedException("Only SNMP v2c is supported");
×
348
            }
349

350
            var message = new TrapV2Message(requestId, version, community, enterprise, timestamp, variables);
×
351
            await message.SendAsync(receiver, token).ConfigureAwait(false);
×
352
        }
×
353

354
        /// <summary>
355
        /// Sends INFORM message.
356
        /// </summary>
357
        /// <param name="requestId">The request ID.</param>
358
        /// <param name="version">Protocol version.</param>
359
        /// <param name="receiver">Receiver.</param>
360
        /// <param name="community">Community name.</param>
361
        /// <param name="contextName">Context name.</param>
362
        /// <param name="enterprise">Enterprise OID.</param>
363
        /// <param name="timestamp">Timestamp.</param>
364
        /// <param name="variables">Variable bindings.</param>
365
        /// <param name="privacy">The privacy provider.</param>
366
        /// <param name="report">The report.</param>
367
        /// <param name="token">The cancellation token.</param>
368
        /// <remarks>This method supports SNMP v2c and v3.</remarks>
369
        [CLSCompliant(false)]
370
        [RequiresUnreferencedCode("SendInformAsync is incompatible with trimming.")]
371
        public static async Task SendInformAsync(int requestId, VersionCode version, IPEndPoint receiver, OctetString community, OctetString contextName, ObjectIdentifier enterprise, uint timestamp, IList<Variable> variables, IPrivacyProvider privacy, ISnmpMessage report, CancellationToken token)
372
        {
373
            if (receiver == null)
×
374
            {
375
                throw new ArgumentNullException(nameof(receiver));
×
376
            }
377

378
            if (community == null)
×
379
            {
380
                throw new ArgumentNullException(nameof(community));
×
381
            }
382

383
            if (contextName == null)
×
384
            {
385
                throw new ArgumentNullException(nameof(contextName));
×
386
            }
387

388
            if (enterprise == null)
×
389
            {
390
                throw new ArgumentNullException(nameof(enterprise));
×
391
            }
392

393
            if (variables == null)
×
394
            {
395
                throw new ArgumentNullException(nameof(variables));
×
396
            }
397

398
            if (version == VersionCode.V1)
×
399
            {
400
                throw new NotSupportedException("SNMP v1 is not supported");
×
401
            }
402

403
            if (version == VersionCode.V3 && privacy == null)
×
404
            {
405
                throw new ArgumentNullException(nameof(privacy));
×
406
            }
407

408
            if (version == VersionCode.V3 && report == null)
×
409
            {
410
                throw new ArgumentNullException(nameof(report));
×
411
            }
412

413
            var message = version == VersionCode.V3
×
414
                                    ? new InformRequestMessage(
×
415
                                          version,
×
416
                                          Messenger.NextMessageId,
×
417
                                          requestId,
×
418
                                          community,
×
419
                                          contextName,
×
420
                                          enterprise,
×
421
                                          timestamp,
×
422
                                          variables,
×
423
                                          privacy,
×
424
                                          Messenger.MaxMessageSize,
×
425
                                          report)
×
426
                                    : new InformRequestMessage(
×
427
                                          requestId,
×
428
                                          version,
×
429
                                          community,
×
430
                                          enterprise,
×
431
                                          timestamp,
×
432
                                          variables);
×
433

434
            var response = await message.GetResponseAsync(receiver, token).ConfigureAwait(false);
×
435
            if (response.Pdu().ErrorStatus.ToInt32() != 0)
×
436
            {
437
                throw ErrorException.Create(
×
438
                    "error in response",
×
439
                    receiver.Address,
×
440
                    response);
×
441
            }
442
        }
×
443

444
        /// <summary>
445
        /// Determines whether the specified seed has next item.
446
        /// </summary>
447
        /// <param name="version">The version.</param>
448
        /// <param name="receiver">The receiver.</param>
449
        /// <param name="community">The community name (v2c) or user name (v3).</param>
450
        /// <param name="contextName">The context name.</param>
451
        /// <param name="seed">The seed.</param>
452
        /// <param name="maxRepetitions">The max repetitions.</param>
453
        /// <param name="privacy">The privacy provider.</param>
454
        /// <param name="report">The report.</param>
455
        /// <param name="token">The cancellation token.</param>
456
        /// <returns>
457
        /// <c>true</c> if the specified seed has next item; otherwise, <c>false</c>.
458
        /// </returns>
459
        /// <remarks>This method supports SNMP v2c and v3.</remarks>
460
        [RequiresUnreferencedCode("BulkHasNextAsync is incompatible with trimming.")]
461
        private static async Task<Tuple<bool, IList<Variable>, ISnmpMessage>> BulkHasNextAsync(VersionCode version, IPEndPoint receiver, OctetString community, OctetString contextName, Variable seed, int maxRepetitions, IPrivacyProvider privacy, ISnmpMessage report, CancellationToken token)
462
        {
463
            // TODO: report should be updated with latest message from agent.
464
            if (version == VersionCode.V1)
×
465
            {
466
                throw new NotSupportedException("SNMP v1 is not supported");
×
467
            }
468

469
            var variables = new List<Variable> { new(seed.Id) };
×
470
            var request = version == VersionCode.V3
×
471
                                                ? new GetBulkRequestMessage(
×
472
                                                      version,
×
473
                                                      Messenger.NextMessageId,
×
474
                                                      Messenger.NextRequestId,
×
475
                                                      community,
×
476
                                                      contextName,
×
477
                                                      0,
×
478
                                                      maxRepetitions,
×
479
                                                      variables,
×
480
                                                      privacy,
×
481
                                                      Messenger.MaxMessageSize,
×
482
                                                      report)
×
483
                                                : new GetBulkRequestMessage(
×
484
                                                      Messenger.NextRequestId,
×
485
                                                      version,
×
486
                                                      community,
×
487
                                                      0,
×
488
                                                      maxRepetitions,
×
489
                                                      variables);
×
490
            var reply = await request.GetResponseAsync(receiver, token).ConfigureAwait(false);
×
491
            if (reply is ReportMessage)
×
492
            {
493
                if (reply.Pdu().Variables.Count == 0)
×
494
                {
495
                    // TODO: whether it is good to return?
496
                    return new Tuple<bool, IList<Variable>, ISnmpMessage>(false, new List<Variable>(0), report);
×
497
                }
498

499
                var id = reply.Pdu().Variables[0].Id;
×
500
                if (id != Messenger.NotInTimeWindow)
×
501
                {
502
                    return new Tuple<bool, IList<Variable>, ISnmpMessage>(false, new List<Variable>(0), report);
×
503
                }
504

505
                // according to RFC 3414, send a second request to sync time.
506
                request = new GetBulkRequestMessage(
×
507
                    version,
×
508
                    Messenger.NextMessageId,
×
509
                    Messenger.NextRequestId,
×
510
                    community,
×
511
                    contextName,
×
512
                    0,
×
513
                    maxRepetitions,
×
514
                    variables,
×
515
                    privacy,
×
516
                    Messenger.MaxMessageSize,
×
517
                    reply);
×
518
                reply = await request.GetResponseAsync(receiver, token).ConfigureAwait(false);
×
519
            }
520
            else if (reply.Pdu().ErrorStatus.ToInt32() != 0)
×
521
            {
522
                throw ErrorException.Create(
×
523
                    "error in response",
×
524
                    receiver.Address,
×
525
                    reply);
×
526
            }
527

528
            var next = reply.Pdu().Variables;
×
529
            return new Tuple<bool, IList<Variable>, ISnmpMessage>(next.Count != 0, next, request);
×
530
        }
×
531

532
        #endregion
533
    }
534
}
535
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc