// Messenger class.// Copyright (C) 2009-2010 Lex Li// // Permission is hereby granted, free of charge, to any person obtaining a copy of this// software and associated documentation files (the "Software"), to deal in the Software// without restriction, including without limitation the rights to use, copy, modify, merge,// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons// to whom the Software is furnished to do so, subject to the following conditions:// // The above copyright notice and this permission notice shall be included in all copies or// substantial portions of the Software.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER// DEALINGS IN THE SOFTWARE. /* * Created by SharpDevelop. * User: lextm * Date: 2009/3/29 * Time: 17:52 * * To change this template use Tools | Options | Coding | Edit Standard Headers. */using System;using System.Collections.Generic;using System.Diagnostics.CodeAnalysis;using System.Globalization;using System.Net;using System.Threading.Tasks;using GSF.Net.Snmp.Security; namespace GSF.Net.Snmp.Messaging{ /// <summary> /// Messenger class contains all static helper methods you need to send out SNMP messages. /// Static methods in Manager or Agent class will be removed in the future. /// </summary> /// <remarks> /// SNMP v3 is not supported in many methods of this class. Please use <see cref="ISnmpMessage" /> derived classes directly /// if you want to do v3 operations. /// </remarks> public static class Messenger { /// <summary> /// RFC 3416 (3.) /// </summary> private static readonly Lazy<NumberGenerator> RequestCounterFullRange = new Lazy<NumberGenerator>(() => new NumberGenerator(int.MinValue, int.MaxValue)); private static readonly Lazy<NumberGenerator> RequestCounterPositive = new Lazy<NumberGenerator>(() => new NumberGenerator(0, int.MaxValue)); private static NumberGenerator RequestCounter { get { return UseFullRange ? RequestCounterFullRange.Value : RequestCounterPositive.Value; } } /// <summary> /// A flag to control request ID range. /// </summary> /// <remarks>Default is <code>true</code>. /// Should be set to <code>false</code> when SNMP devices might not support negative request ID values. /// </remarks> public static bool UseFullRange { get; set; } = true; /// <summary> /// RFC 3412 (6.) /// </summary> private static readonly NumberGenerator MessageCounter = new NumberGenerator(0, int.MaxValue); private static readonly ObjectIdentifier IdUnsupportedSecurityLevel = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 }); private static readonly ObjectIdentifier IdNotInTimeWindow = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 }); private static readonly ObjectIdentifier IdUnknownSecurityName = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 }); private static readonly ObjectIdentifier IdUnknownEngineID = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 }); private static readonly ObjectIdentifier IdAuthenticationFailure = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 }); private static readonly ObjectIdentifier IdDecryptionError = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 }); #region async methods /// <summary> /// Gets a list of variable binds. /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name.</param> /// <param name="variables">Variable binds.</param> /// <returns></returns> public static async Task<IList<Variable>> GetAsync(VersionCode version, IPEndPoint endpoint, OctetString community, IList<Variable> variables) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (community == null) { throw new ArgumentNullException(nameof(community)); } if (variables == null) { throw new ArgumentNullException(nameof(variables)); } if (version == VersionCode.V3) { throw new NotSupportedException("SNMP v3 is not supported"); } GetRequestMessage message = new GetRequestMessage(RequestCounter.NextId, version, community, variables); ISnmpMessage response = await message.GetResponseAsync(endpoint).ConfigureAwait(false); ISnmpPdu pdu = response.Pdu(); if (pdu.ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", endpoint.Address, response); } return pdu.Variables; } /// <summary> /// Sets a list of variable binds. /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name.</param> /// <param name="variables">Variable binds.</param> /// <returns></returns> public static async Task<IList<Variable>> SetAsync(VersionCode version, IPEndPoint endpoint, OctetString community, IList<Variable> variables) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (community == null) { throw new ArgumentNullException(nameof(community)); } if (variables == null) { throw new ArgumentNullException(nameof(variables)); } if (version == VersionCode.V3) { throw new NotSupportedException("SNMP v3 is not supported"); } SetRequestMessage message = new SetRequestMessage(RequestCounter.NextId, version, community, variables); ISnmpMessage response = await message.GetResponseAsync(endpoint).ConfigureAwait(false); ISnmpPdu pdu = response.Pdu(); if (pdu.ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", endpoint.Address, response); } return pdu.Variables; } /// <summary> /// Walks (based on GET NEXT). /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name.</param> /// <param name="table">OID.</param> /// <param name="list">A list to hold the results.</param> /// <param name="mode">Walk mode.</param> /// <returns> /// Returns row count if the OID is a table. Otherwise this value is meaningless. /// </returns> /// <remarks>This method only supports SNMP v1 and v2c.</remarks> public static async Task<int> WalkAsync(VersionCode version, IPEndPoint endpoint, OctetString community, ObjectIdentifier table, IList<Variable> list, WalkMode mode) { if (list == null) { throw new ArgumentNullException(nameof(list)); } int result = 0; Variable tableV = new Variable(table); Variable seed; Variable next = tableV; string rowMask = string.Format(CultureInfo.InvariantCulture, "{0}.1.1.", table); string subTreeMask = string.Format(CultureInfo.InvariantCulture, "{0}.", table); Tuple<bool, Variable> data = new Tuple<bool, Variable>(false, next); do { seed = data.Item2; if (seed == tableV) { data = await HasNextAsync(version, endpoint, community, seed).ConfigureAwait(false); continue; } if (mode == WalkMode.WithinSubtree && !seed.Id.ToString().StartsWith(subTreeMask, StringComparison.Ordinal)) { // not in sub tree break; } list.Add(seed); if (seed.Id.ToString().StartsWith(rowMask, StringComparison.Ordinal)) { result++; } data = await HasNextAsync(version, endpoint, community, seed).ConfigureAwait(false); } while (data.Item1); return result; } /// <summary> /// Determines whether the specified seed has next item. /// </summary> /// <param name="version">The version.</param> /// <param name="endpoint">The endpoint.</param> /// <param name="community">The community.</param> /// <param name="seed">The seed.</param> /// <returns> /// <c>true</c> if the specified seed has next item; otherwise, <c>false</c>. /// </returns> /// <remarks>This method only supports SNMP v1 and v2c.</remarks> private static async Task<Tuple<bool, Variable>> HasNextAsync(VersionCode version, IPEndPoint endpoint, OctetString community, Variable seed) { if (seed == null) { throw new ArgumentNullException(nameof(seed)); } List<Variable> variables = new List<Variable> { new Variable(seed.Id) }; GetNextRequestMessage message = new GetNextRequestMessage( RequestCounter.NextId, version, community, variables); ISnmpMessage response = await message.GetResponseAsync(endpoint).ConfigureAwait(false); ISnmpPdu pdu = response.Pdu(); bool errorFound = pdu.ErrorStatus.ToErrorCode() == ErrorCode.NoSuchName; return new Tuple<bool, Variable>(!errorFound, errorFound ? null : pdu.Variables[0]); } /// <summary> /// Walks (based on GET BULK). /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name (v2c) or user name (v3).</param> /// <param name="table">OID.</param> /// <param name="list">A list to hold the results.</param> /// <param name="maxRepetitions">The max repetitions.</param> /// <param name="mode">Walk mode.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <returns>Returns row count if the OID is a table. Otherwise this value is meaningless.</returns> /// <remarks>This method only supports SNMP v2c and v3.</remarks> [Obsolete("Please use other overloading ones.")] public static async Task<int> BulkWalkAsync(VersionCode version, IPEndPoint endpoint, OctetString community, ObjectIdentifier table, IList<Variable> list, int maxRepetitions, WalkMode mode, IPrivacyProvider privacy, ISnmpMessage report) => await BulkWalkAsync(version, endpoint, community, OctetString.Empty, table, list, maxRepetitions, mode, privacy, report); /// <summary> /// Walks (based on GET BULK). /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name (v2c) or user name (v3).</param> /// <param name="contextName">Context name.</param> /// <param name="table">OID.</param> /// <param name="list">A list to hold the results.</param> /// <param name="maxRepetitions">The max repetitions.</param> /// <param name="mode">Walk mode.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <returns>Returns row count if the OID is a table. Otherwise this value is meaningless.</returns> /// <remarks>This method only supports SNMP v2c and v3.</remarks> 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) { if (list == null) { throw new ArgumentNullException(nameof(list)); } Variable tableV = new Variable(table); Variable seed = tableV; int result = 0; ISnmpMessage message = report; Tuple<bool, IList<Variable>, ISnmpMessage> data = await BulkHasNextAsync(version, endpoint, community, contextName, seed, maxRepetitions, privacy, message).ConfigureAwait(false); IList<Variable> next = data.Item2; message = data.Item3; while (data.Item1) { string subTreeMask = string.Format(CultureInfo.InvariantCulture, "{0}.", table); string rowMask = string.Format(CultureInfo.InvariantCulture, "{0}.1.1.", table); foreach (Variable v in next) { string id = v.Id.ToString(); if (v.Data.TypeCode == SnmpType.EndOfMibView) { goto end; } if (mode == WalkMode.WithinSubtree && !id.StartsWith(subTreeMask, StringComparison.Ordinal)) { // not in sub tree goto end; } list.Add(v); if (id.StartsWith(rowMask, StringComparison.Ordinal)) { result++; } } seed = next[next.Count - 1]; data = await BulkHasNextAsync(version, endpoint, community, contextName, seed, maxRepetitions, privacy, message).ConfigureAwait(false); next = data.Item2; message = data.Item3; } end: return result; } /// <summary> /// Sends a TRAP v1 message. /// </summary> /// <param name="receiver">Receiver.</param> /// <param name="agent">Agent.</param> /// <param name="community">Community name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="generic">Generic code.</param> /// <param name="specific">Specific code.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <remarks>This method only supports SNMP v1.</remarks> [CLSCompliant(false)] public static async Task SendTrapV1Async(EndPoint receiver, IPAddress agent, OctetString community, ObjectIdentifier enterprise, GenericCode generic, int specific, uint timestamp, IList<Variable> variables) { TrapV1Message message = new TrapV1Message(VersionCode.V1, agent, community, enterprise, generic, specific, timestamp, variables); await message.SendAsync(receiver).ConfigureAwait(false); } /// <summary> /// Sends TRAP v2 message. /// </summary> /// <param name="version">Protocol version.</param> /// <param name="receiver">Receiver.</param> /// <param name="community">Community name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <param name="requestId">Request ID.</param> /// <remarks>This method only supports SNMP v2c.</remarks> [CLSCompliant(false)] public static async Task SendTrapV2Async(int requestId, VersionCode version, EndPoint receiver, OctetString community, ObjectIdentifier enterprise, uint timestamp, IList<Variable> variables) { if (version != VersionCode.V2) { throw new NotSupportedException("Only SNMP v2c is supported"); } TrapV2Message message = new TrapV2Message(requestId, version, community, enterprise, timestamp, variables); await message.SendAsync(receiver).ConfigureAwait(false); } /// <summary> /// Sends INFORM message. /// </summary> /// <param name="requestId">The request id.</param> /// <param name="version">Protocol version.</param> /// <param name="receiver">Receiver.</param> /// <param name="community">Community name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <remarks>This method supports SNMP v2c and v3.</remarks> [CLSCompliant(false)] [Obsolete("Please use other overloading ones.")] public static async Task SendInformAsync(int requestId, VersionCode version, IPEndPoint receiver, OctetString community, ObjectIdentifier enterprise, uint timestamp, IList<Variable> variables, IPrivacyProvider privacy, ISnmpMessage report) => await SendInformAsync(requestId, version, receiver, community, OctetString.Empty, enterprise, timestamp, variables, privacy, report); /// <summary> /// Sends INFORM message. /// </summary> /// <param name="requestId">The request ID.</param> /// <param name="version">Protocol version.</param> /// <param name="receiver">Receiver.</param> /// <param name="community">Community name.</param> /// <param name="contextName">Context name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <remarks>This method supports SNMP v2c and v3.</remarks> [CLSCompliant(false)] 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) { if (receiver == null) { throw new ArgumentNullException(nameof(receiver)); } if (community == null) { throw new ArgumentNullException(nameof(community)); } if (contextName == null) { throw new ArgumentNullException(nameof(contextName)); } if (enterprise == null) { throw new ArgumentNullException(nameof(enterprise)); } if (variables == null) { throw new ArgumentNullException(nameof(variables)); } if (version == VersionCode.V1) { throw new NotSupportedException("SNMP v1 is not supported"); } if (version == VersionCode.V3 && privacy == null) { throw new ArgumentNullException(nameof(privacy)); } if (version == VersionCode.V3 && report == null) { throw new ArgumentNullException(nameof(report)); } InformRequestMessage message = version == VersionCode.V3 ? new InformRequestMessage( version, MessageCounter.NextId, requestId, community, contextName, enterprise, timestamp, variables, privacy, MaxMessageSize, report) : new InformRequestMessage( requestId, version, community, enterprise, timestamp, variables); ISnmpMessage response = await message.GetResponseAsync(receiver).ConfigureAwait(false); if (response.Pdu().ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", receiver.Address, response); } } /// <summary> /// Determines whether the specified seed has next item. /// </summary> /// <param name="version">The version.</param> /// <param name="receiver">The receiver.</param> /// <param name="community">Community name (v2c) or user name (v3).</param> /// <param name="seed">The seed.</param> /// <param name="maxRepetitions">The max repetitions.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <returns> /// <c>true</c> if the specified seed has next item; otherwise, <c>false</c>. /// </returns> /// <remarks>This method supports SNMP v2c and v3.</remarks> [Obsolete("Please use other overloading ones.")] private static async Task<Tuple<bool, IList<Variable>, ISnmpMessage>> BulkHasNextAsync(VersionCode version, IPEndPoint receiver, OctetString community, Variable seed, int maxRepetitions, IPrivacyProvider privacy, ISnmpMessage report) => await BulkHasNextAsync(version, receiver, community, OctetString.Empty, seed, maxRepetitions, privacy, report); Lines 1–500 of 1336. Load more
// Messenger class. // Copyright (C) 2009-2010 Lex Li // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. /* * Created by SharpDevelop. * User: lextm * Date: 2009/3/29 * Time: 17:52 * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Net; using System.Threading.Tasks; using GSF.Net.Snmp.Security; namespace GSF.Net.Snmp.Messaging { /// <summary> /// Messenger class contains all static helper methods you need to send out SNMP messages. /// Static methods in Manager or Agent class will be removed in the future. /// </summary> /// <remarks> /// SNMP v3 is not supported in many methods of this class. Please use <see cref="ISnmpMessage" /> derived classes directly /// if you want to do v3 operations. /// </remarks> public static class Messenger { /// <summary> /// RFC 3416 (3.) /// </summary> private static readonly Lazy<NumberGenerator> RequestCounterFullRange = new Lazy<NumberGenerator>(() => new NumberGenerator(int.MinValue, int.MaxValue)); private static readonly Lazy<NumberGenerator> RequestCounterPositive = new Lazy<NumberGenerator>(() => new NumberGenerator(0, int.MaxValue)); private static NumberGenerator RequestCounter { get { return UseFullRange ? RequestCounterFullRange.Value : RequestCounterPositive.Value; } } /// <summary> /// A flag to control request ID range. /// </summary> /// <remarks>Default is <code>true</code>. /// Should be set to <code>false</code> when SNMP devices might not support negative request ID values. /// </remarks> public static bool UseFullRange { get; set; } = true; /// <summary> /// RFC 3412 (6.) /// </summary> private static readonly NumberGenerator MessageCounter = new NumberGenerator(0, int.MaxValue); private static readonly ObjectIdentifier IdUnsupportedSecurityLevel = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 }); private static readonly ObjectIdentifier IdNotInTimeWindow = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 }); private static readonly ObjectIdentifier IdUnknownSecurityName = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 }); private static readonly ObjectIdentifier IdUnknownEngineID = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 }); private static readonly ObjectIdentifier IdAuthenticationFailure = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 }); private static readonly ObjectIdentifier IdDecryptionError = new ObjectIdentifier(new uint[] { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 }); #region async methods /// <summary> /// Gets a list of variable binds. /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name.</param> /// <param name="variables">Variable binds.</param> /// <returns></returns> public static async Task<IList<Variable>> GetAsync(VersionCode version, IPEndPoint endpoint, OctetString community, IList<Variable> variables) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (community == null) { throw new ArgumentNullException(nameof(community)); } if (variables == null) { throw new ArgumentNullException(nameof(variables)); } if (version == VersionCode.V3) { throw new NotSupportedException("SNMP v3 is not supported"); } GetRequestMessage message = new GetRequestMessage(RequestCounter.NextId, version, community, variables); ISnmpMessage response = await message.GetResponseAsync(endpoint).ConfigureAwait(false); ISnmpPdu pdu = response.Pdu(); if (pdu.ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", endpoint.Address, response); } return pdu.Variables; } /// <summary> /// Sets a list of variable binds. /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name.</param> /// <param name="variables">Variable binds.</param> /// <returns></returns> public static async Task<IList<Variable>> SetAsync(VersionCode version, IPEndPoint endpoint, OctetString community, IList<Variable> variables) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (community == null) { throw new ArgumentNullException(nameof(community)); } if (variables == null) { throw new ArgumentNullException(nameof(variables)); } if (version == VersionCode.V3) { throw new NotSupportedException("SNMP v3 is not supported"); } SetRequestMessage message = new SetRequestMessage(RequestCounter.NextId, version, community, variables); ISnmpMessage response = await message.GetResponseAsync(endpoint).ConfigureAwait(false); ISnmpPdu pdu = response.Pdu(); if (pdu.ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", endpoint.Address, response); } return pdu.Variables; } /// <summary> /// Walks (based on GET NEXT). /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name.</param> /// <param name="table">OID.</param> /// <param name="list">A list to hold the results.</param> /// <param name="mode">Walk mode.</param> /// <returns> /// Returns row count if the OID is a table. Otherwise this value is meaningless. /// </returns> /// <remarks>This method only supports SNMP v1 and v2c.</remarks> public static async Task<int> WalkAsync(VersionCode version, IPEndPoint endpoint, OctetString community, ObjectIdentifier table, IList<Variable> list, WalkMode mode) { if (list == null) { throw new ArgumentNullException(nameof(list)); } int result = 0; Variable tableV = new Variable(table); Variable seed; Variable next = tableV; string rowMask = string.Format(CultureInfo.InvariantCulture, "{0}.1.1.", table); string subTreeMask = string.Format(CultureInfo.InvariantCulture, "{0}.", table); Tuple<bool, Variable> data = new Tuple<bool, Variable>(false, next); do { seed = data.Item2; if (seed == tableV) { data = await HasNextAsync(version, endpoint, community, seed).ConfigureAwait(false); continue; } if (mode == WalkMode.WithinSubtree && !seed.Id.ToString().StartsWith(subTreeMask, StringComparison.Ordinal)) { // not in sub tree break; } list.Add(seed); if (seed.Id.ToString().StartsWith(rowMask, StringComparison.Ordinal)) { result++; } data = await HasNextAsync(version, endpoint, community, seed).ConfigureAwait(false); } while (data.Item1); return result; } /// <summary> /// Determines whether the specified seed has next item. /// </summary> /// <param name="version">The version.</param> /// <param name="endpoint">The endpoint.</param> /// <param name="community">The community.</param> /// <param name="seed">The seed.</param> /// <returns> /// <c>true</c> if the specified seed has next item; otherwise, <c>false</c>. /// </returns> /// <remarks>This method only supports SNMP v1 and v2c.</remarks> private static async Task<Tuple<bool, Variable>> HasNextAsync(VersionCode version, IPEndPoint endpoint, OctetString community, Variable seed) { if (seed == null) { throw new ArgumentNullException(nameof(seed)); } List<Variable> variables = new List<Variable> { new Variable(seed.Id) }; GetNextRequestMessage message = new GetNextRequestMessage( RequestCounter.NextId, version, community, variables); ISnmpMessage response = await message.GetResponseAsync(endpoint).ConfigureAwait(false); ISnmpPdu pdu = response.Pdu(); bool errorFound = pdu.ErrorStatus.ToErrorCode() == ErrorCode.NoSuchName; return new Tuple<bool, Variable>(!errorFound, errorFound ? null : pdu.Variables[0]); } /// <summary> /// Walks (based on GET BULK). /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name (v2c) or user name (v3).</param> /// <param name="table">OID.</param> /// <param name="list">A list to hold the results.</param> /// <param name="maxRepetitions">The max repetitions.</param> /// <param name="mode">Walk mode.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <returns>Returns row count if the OID is a table. Otherwise this value is meaningless.</returns> /// <remarks>This method only supports SNMP v2c and v3.</remarks> [Obsolete("Please use other overloading ones.")] public static async Task<int> BulkWalkAsync(VersionCode version, IPEndPoint endpoint, OctetString community, ObjectIdentifier table, IList<Variable> list, int maxRepetitions, WalkMode mode, IPrivacyProvider privacy, ISnmpMessage report) => await BulkWalkAsync(version, endpoint, community, OctetString.Empty, table, list, maxRepetitions, mode, privacy, report); /// <summary> /// Walks (based on GET BULK). /// </summary> /// <param name="version">Protocol version.</param> /// <param name="endpoint">Endpoint.</param> /// <param name="community">Community name (v2c) or user name (v3).</param> /// <param name="contextName">Context name.</param> /// <param name="table">OID.</param> /// <param name="list">A list to hold the results.</param> /// <param name="maxRepetitions">The max repetitions.</param> /// <param name="mode">Walk mode.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <returns>Returns row count if the OID is a table. Otherwise this value is meaningless.</returns> /// <remarks>This method only supports SNMP v2c and v3.</remarks> 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) { if (list == null) { throw new ArgumentNullException(nameof(list)); } Variable tableV = new Variable(table); Variable seed = tableV; int result = 0; ISnmpMessage message = report; Tuple<bool, IList<Variable>, ISnmpMessage> data = await BulkHasNextAsync(version, endpoint, community, contextName, seed, maxRepetitions, privacy, message).ConfigureAwait(false); IList<Variable> next = data.Item2; message = data.Item3; while (data.Item1) { string subTreeMask = string.Format(CultureInfo.InvariantCulture, "{0}.", table); string rowMask = string.Format(CultureInfo.InvariantCulture, "{0}.1.1.", table); foreach (Variable v in next) { string id = v.Id.ToString(); if (v.Data.TypeCode == SnmpType.EndOfMibView) { goto end; } if (mode == WalkMode.WithinSubtree && !id.StartsWith(subTreeMask, StringComparison.Ordinal)) { // not in sub tree goto end; } list.Add(v); if (id.StartsWith(rowMask, StringComparison.Ordinal)) { result++; } } seed = next[next.Count - 1]; data = await BulkHasNextAsync(version, endpoint, community, contextName, seed, maxRepetitions, privacy, message).ConfigureAwait(false); next = data.Item2; message = data.Item3; } end: return result; } /// <summary> /// Sends a TRAP v1 message. /// </summary> /// <param name="receiver">Receiver.</param> /// <param name="agent">Agent.</param> /// <param name="community">Community name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="generic">Generic code.</param> /// <param name="specific">Specific code.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <remarks>This method only supports SNMP v1.</remarks> [CLSCompliant(false)] public static async Task SendTrapV1Async(EndPoint receiver, IPAddress agent, OctetString community, ObjectIdentifier enterprise, GenericCode generic, int specific, uint timestamp, IList<Variable> variables) { TrapV1Message message = new TrapV1Message(VersionCode.V1, agent, community, enterprise, generic, specific, timestamp, variables); await message.SendAsync(receiver).ConfigureAwait(false); } /// <summary> /// Sends TRAP v2 message. /// </summary> /// <param name="version">Protocol version.</param> /// <param name="receiver">Receiver.</param> /// <param name="community">Community name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <param name="requestId">Request ID.</param> /// <remarks>This method only supports SNMP v2c.</remarks> [CLSCompliant(false)] public static async Task SendTrapV2Async(int requestId, VersionCode version, EndPoint receiver, OctetString community, ObjectIdentifier enterprise, uint timestamp, IList<Variable> variables) { if (version != VersionCode.V2) { throw new NotSupportedException("Only SNMP v2c is supported"); } TrapV2Message message = new TrapV2Message(requestId, version, community, enterprise, timestamp, variables); await message.SendAsync(receiver).ConfigureAwait(false); } /// <summary> /// Sends INFORM message. /// </summary> /// <param name="requestId">The request id.</param> /// <param name="version">Protocol version.</param> /// <param name="receiver">Receiver.</param> /// <param name="community">Community name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <remarks>This method supports SNMP v2c and v3.</remarks> [CLSCompliant(false)] [Obsolete("Please use other overloading ones.")] public static async Task SendInformAsync(int requestId, VersionCode version, IPEndPoint receiver, OctetString community, ObjectIdentifier enterprise, uint timestamp, IList<Variable> variables, IPrivacyProvider privacy, ISnmpMessage report) => await SendInformAsync(requestId, version, receiver, community, OctetString.Empty, enterprise, timestamp, variables, privacy, report); /// <summary> /// Sends INFORM message. /// </summary> /// <param name="requestId">The request ID.</param> /// <param name="version">Protocol version.</param> /// <param name="receiver">Receiver.</param> /// <param name="community">Community name.</param> /// <param name="contextName">Context name.</param> /// <param name="enterprise">Enterprise OID.</param> /// <param name="timestamp">Timestamp.</param> /// <param name="variables">Variable bindings.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <remarks>This method supports SNMP v2c and v3.</remarks> [CLSCompliant(false)] 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) { if (receiver == null) { throw new ArgumentNullException(nameof(receiver)); } if (community == null) { throw new ArgumentNullException(nameof(community)); } if (contextName == null) { throw new ArgumentNullException(nameof(contextName)); } if (enterprise == null) { throw new ArgumentNullException(nameof(enterprise)); } if (variables == null) { throw new ArgumentNullException(nameof(variables)); } if (version == VersionCode.V1) { throw new NotSupportedException("SNMP v1 is not supported"); } if (version == VersionCode.V3 && privacy == null) { throw new ArgumentNullException(nameof(privacy)); } if (version == VersionCode.V3 && report == null) { throw new ArgumentNullException(nameof(report)); } InformRequestMessage message = version == VersionCode.V3 ? new InformRequestMessage( version, MessageCounter.NextId, requestId, community, contextName, enterprise, timestamp, variables, privacy, MaxMessageSize, report) : new InformRequestMessage( requestId, version, community, enterprise, timestamp, variables); ISnmpMessage response = await message.GetResponseAsync(receiver).ConfigureAwait(false); if (response.Pdu().ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", receiver.Address, response); } } /// <summary> /// Determines whether the specified seed has next item. /// </summary> /// <param name="version">The version.</param> /// <param name="receiver">The receiver.</param> /// <param name="community">Community name (v2c) or user name (v3).</param> /// <param name="seed">The seed.</param> /// <param name="maxRepetitions">The max repetitions.</param> /// <param name="privacy">The privacy provider.</param> /// <param name="report">The report.</param> /// <returns> /// <c>true</c> if the specified seed has next item; otherwise, <c>false</c>. /// </returns> /// <remarks>This method supports SNMP v2c and v3.</remarks> [Obsolete("Please use other overloading ones.")] private static async Task<Tuple<bool, IList<Variable>, ISnmpMessage>> BulkHasNextAsync(VersionCode version, IPEndPoint receiver, OctetString community, Variable seed, int maxRepetitions, IPrivacyProvider privacy, ISnmpMessage report) => await BulkHasNextAsync(version, receiver, community, OctetString.Empty, seed, maxRepetitions, privacy, report);