1336 lines · 61.2 KB · C#
RawDownload
// 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t