예제 #1
0
        public void TestTrapV3AuthBytes()
        {
            byte[]       bytes                = Properties.Resources.v3authNoPriv_BER_Issue;
            UserRegistry registry             = new UserRegistry();
            SHA1AuthenticationProvider authen = new SHA1AuthenticationProvider(new OctetString("testpass"));

            registry.Add(new OctetString("test"), new DefaultPrivacyProvider(authen));
            IList <ISnmpMessage> messages = MessageFactory.ParseMessages(bytes, registry);

            Assert.Equal(1, messages.Count);
            ISnmpMessage message = messages[0];

            Assert.Equal("80001299030005B706CF69", message.Parameters.EngineId.ToHexString());
            Assert.Equal(41, message.Parameters.EngineBoots.ToInt32());
            Assert.Equal(877, message.Parameters.EngineTime.ToInt32());
            Assert.Equal("test", message.Parameters.UserName.ToString());
            Assert.Equal("C107F9DAA3FC552960E38936", message.Parameters.AuthenticationParameters.ToHexString());
            Assert.Equal("", message.Parameters.PrivacyParameters.ToHexString());
            Assert.Equal("80001299030005B706CF69", message.Scope.ContextEngineId.ToHexString()); // SNMP#NET returns string.Empty here.
            Assert.Equal("", message.Scope.ContextName.ToHexString());
            Assert.Equal(681323585, message.MessageId());
            Assert.Equal(681323584, message.RequestId());

            Console.WriteLine(new OctetString(bytes).ToHexString());
            Console.WriteLine(new OctetString(message.ToBytes()).ToHexString());
            Assert.Equal(bytes, message.ToBytes());
        }
예제 #2
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static void SendAsync(this ISnmpMessage message, EndPoint manager, Socket socket)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (socket == null)
            {
                throw new ArgumentNullException("socket");
            }

            if (manager == null)
            {
                throw new ArgumentNullException("manager");
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                                                                  "not a trap message: {0}",
                                                                  code));
            }

            byte[] bytes = message.ToBytes();
            socket.BeginSendTo(bytes, 0, bytes.Length, SocketFlags.None, manager, ar => socket.EndSendTo(ar), null);
        }
예제 #3
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        /// <param name="token">The cancellation token.</param>
        public static async Task SendAsync(this ISnmpMessage message, EndPoint manager, Socket socket, CancellationToken token)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            var buffer = new ArraySegment <byte>(message.ToBytes());
            await socket.SendToAsync(buffer, SocketFlags.None, manager, token);
        }
예제 #4
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static async Task SendAsync(this ISnmpMessage message, IPEndPoint manager, UdpClient socket)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            var bytes = message.ToBytes();

            socket.Connect(manager);
            await socket.SendAsync(bytes, bytes.Length);
        }
예제 #5
0
        /// <summary>
        /// Sends a response message.
        /// </summary>
        /// <param name="response">
        /// A <see cref="ISnmpMessage"/>.
        /// </param>
        /// <param name="receiver">Receiver.</param>
        public void SendResponse(ISnmpMessage response, EndPoint receiver)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            if (_disposed)
            {
                throw new ObjectDisposedException("Listener");
            }

            if (_socket == null)
            {
                return;
            }

            byte[] buffer = response.ToBytes();
# if !SILVERLIGHT  // mc++
예제 #6
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static async Task SendAsync(this ISnmpMessage message, EndPoint manager, Socket socket)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (socket == null)
            {
                throw new ArgumentNullException("socket");
            }

            if (manager == null)
            {
                throw new ArgumentNullException("manager");
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a trap message: {0}", code));
            }

            var bytes = message.ToBytes();
            var info  = SocketExtension.EventArgsFactory.Create();

            info.RemoteEndPoint = manager;
            info.SetBuffer(bytes, 0, bytes.Length);
            using (var awaitable1 = new SocketAwaitable(info))
            {
                await socket.SendToAsync(awaitable1);
            }
        }
예제 #7
0
        /// <summary>
        /// Sends a response message.
        /// </summary>
        /// <param name="response">
        /// A <see cref="ISnmpMessage"/>.
        /// </param>
        /// <param name="receiver">Receiver.</param>
        public void SendResponse(ISnmpMessage response, EndPoint receiver)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            if (_disposed)
            {
                throw new ObjectDisposedException("Listener");
            }

            if (_socket == null)
            {
                return;
            }

            var buffer = response.ToBytes();

            _socket.BeginSendTo(buffer, 0, buffer.Length, 0, receiver, ar => _socket.EndSendTo(ar), null);
        }
예제 #8
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="manager">Manager</param>
        /// <param name="socket">The socket.</param>
        public static void Send(this ISnmpMessage message, EndPoint manager, Socket socket)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var code = message.TypeCode();

            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "not a trap message: {0}",
                                                        code));
            }

            var bytes = message.ToBytes();

            socket.SendTo(bytes, 0, bytes.Length, SocketFlags.None, manager);
        }
예제 #9
0
        /// <summary>
        /// Begins to asynchronously send an <see cref="ISnmpMessage"/> to an <see cref="IPEndPoint"/>.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="registry">The user registry.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state object.</param>
        /// <returns></returns>
        public static IAsyncResult BeginGetResponse(
            this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, AsyncCallback callback, object state)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException("udpSocket");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            if (registry == null)
            {
                throw new ArgumentNullException("registry");
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            // Whatever you change, try to keep the Send and the Receive close to each other.
            udpSocket.SendTo(request.ToBytes(), receiver);
#if CF
            var bufferSize = 8192;
#elif SSHARP
            var bufferSize = 16384;
#else
            var bufferSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;
#endif
            var buffer = new byte[bufferSize];

            // https://sharpsnmplib.codeplex.com/workitem/7234
            if (callback != null)
            {
                AsyncCallback wrapped = callback;
                callback = asyncResult =>
                {
                    var result = new SnmpMessageAsyncResult(asyncResult, udpSocket, registry, receiver, buffer);
                    wrapped(result);
                };
            }

            var ar = udpSocket.BeginReceive(buffer, 0, bufferSize, SocketFlags.None, callback, state);
            return(new SnmpMessageAsyncResult(ar, udpSocket, registry, receiver, buffer));
        }
예제 #10
0
        /// <summary>
        /// Sends an  <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="connectionTimeout">The time-out value, in milliseconds for how long to wait for a connection</param>
        /// <param name="responseTimeout">The time-out value, in milliseconds for how long to wait for a response. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="client">The DTLS client</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetSecureResponseAsync(this ISnmpMessage request, TimeSpan connectionTimeout, TimeSpan responseTimeout, IPEndPoint receiver, Client client, UserRegistry registry)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (client is null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes = request.ToBytes();
            await client.ConnectToServerAsync(receiver, responseTimeout, connectionTimeout).ConfigureAwait(false);

            var reply = await client.SendAndGetResponseAsync(bytes, responseTimeout).ConfigureAwait(false);

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, reply.Length, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
예제 #11
0
        public void Test()
        {
            byte[]       expected = Properties.Resources.get;
            ISnmpMessage message  = MessageFactory.ParseMessages(expected, new UserRegistry())[0];

            Assert.Equal(SnmpType.GetRequestPdu, message.TypeCode());
            GetRequestPdu pdu = (GetRequestPdu)message.Pdu();

            Assert.Equal(1, pdu.Variables.Count);
            Variable v = pdu.Variables[0];

            Assert.Equal(new uint[] { 1, 3, 6, 1, 2, 1, 1, 6, 0 }, v.Id.ToNumerical());
            Assert.Equal(typeof(Null), v.Data.GetType());
            Assert.True(expected.Length >= message.ToBytes().Length);
        }
예제 #12
0
        /// <summary>
        /// Sends a response message.
        /// </summary>
        /// <param name="response">
        /// A <see cref="ISnmpMessage"/>.
        /// </param>
        /// <param name="receiver">Receiver.</param>
        public async Task SendResponseAsync(ISnmpMessage response, EndPoint receiver)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (_disposed)
            {
                throw new ObjectDisposedException("Listener");
            }

            if (_socket == null)
            {
                return;
            }

            var buffer = response.ToBytes();
            var info   = SocketExtension.EventArgsFactory.Create();

            try
            {
                info.RemoteEndPoint = receiver;
                info.SetBuffer(buffer, 0, buffer.Length);
                using (var awaitable1 = new SocketAwaitable(info))
                {
                    await _socket.SendToAsync(awaitable1);
                }
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode != SocketError.Interrupted)
                {
                    // IMPORTANT: interrupted means the socket is closed.
                    throw;
                }
            }
        }
예제 #13
0
        /// <summary>
        /// Sends a response message.
        /// </summary>
        /// <param name="response">
        /// A <see cref="ISnmpMessage"/>.
        /// </param>
        /// <param name="receiver">Receiver.</param>
        public void SendResponse(ISnmpMessage response, EndPoint receiver)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            if (_disposed)
            {
                throw new ObjectDisposedException("Listener");
            }

            if (_socket == null)
            {
                return;
            }

            var buffer = response.ToBytes();

            try
            {
                _socket.SendTo(buffer, 0, buffer.Length, 0, receiver);
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode != SocketError.Interrupted)
                {
                    // IMPORTANT: interrupted means the socket is closed.
                    throw;
                }
            }
        }
        /// <summary>
        /// Sends a response message.
        /// </summary>
        /// <param name="response">
        /// A <see cref="ISnmpMessage"/>.
        /// </param>
        /// <param name="receiver">Receiver.</param>
        public async Task SendResponseAsync(ISnmpMessage response, EndPoint receiver)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (_disposed)
            {
                throw new ObjectDisposedException("Listener");
            }

            if (_socket == null)
            {
                return;
            }

            try
            {
                await _socket.SendToAsync(new ArraySegment <byte>(response.ToBytes()), SocketFlags.None, receiver);
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode != SocketError.Interrupted)
                {
                    // IMPORTANT: interrupted means the socket is closed.
                    throw;
                }
            }
        }
예제 #15
0
        internal static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint remoteEndPoint, CancellationToken cancellationToken)
        {
            try
            {
                using var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

                await socket.ConnectAsync(remoteEndPoint, cancellationToken).ConfigureAwait(false);

                var sendingBytes = request.ToBytes();
                await socket.SendAsync(sendingBytes, SocketFlags.None, cancellationToken).ConfigureAwait(false);

                var recvd      = new byte[100000];
                var recvdCount = await socket.ReceiveAsync(recvd, SocketFlags.None, cancellationToken).ConfigureAwait(false);

                var registry = new UserRegistry();
                var response = MessageFactory.ParseMessages(recvd.Take(recvdCount).ToArray(), 0, recvdCount, registry)[0];

                var responseCode = response.TypeCode();
                if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
                {
                    var requestId  = request.MessageId();
                    var responseId = response.MessageId();
                    if (responseId != requestId)
                    {
                        throw OperationException.Create($"wrong response sequence: expected {requestId}, received {responseId}", remoteEndPoint.Address);
                    }

                    return(response);
                }

                throw OperationException.Create($"wrong response type: {responseCode}", remoteEndPoint.Address);
            }
            catch (TaskCanceledException)
            {
                throw new OperationCanceledException(cancellationToken);
            }
        }
예제 #16
0
        /// <summary>
        /// Sends a response message.
        /// </summary>
        /// <param name="response">
        /// A <see cref="ISnmpMessage"/>.
        /// </param>
        /// <param name="receiver">Receiver.</param>
        public void SendResponse(ISnmpMessage response, EndPoint receiver)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            if (_disposed)
            {
                throw new ObjectDisposedException("Listener");
            }

            if (_socket == null)
            {
                return;
            }

            var buffer = response.ToBytes();
            _socket.BeginSendTo(buffer, 0, buffer.Length, 0, receiver, ar => _socket.EndSendTo(ar), null);
        }
예제 #17
0
        public static void Main(string[] args)
        {
            string      community      = "public";
            bool        showHelp       = false;
            bool        showVersion    = false;
            VersionCode version        = VersionCode.V2; // GET BULK is available in SNMP v2 and above.
            int         timeout        = 1000;
            int         retry          = 0;
            Levels      level          = Levels.Reportable;
            string      user           = string.Empty;
            string      authentication = string.Empty;
            string      authPhrase     = string.Empty;
            string      privacy        = string.Empty;
            string      privPhrase     = string.Empty;
            int         maxRepetitions = 10;
            int         nonRepeaters   = 0;
            bool        dump           = false;

            OptionSet p = new OptionSet()
                          .Add("c:", "Community name, (default is public)", delegate(string v) { if (v != null)
                                                                                                 {
                                                                                                     community = v;
                                                                                                 }
                               })
                          .Add("l:", "Security level, (default is noAuthNoPriv)", delegate(string v)
            {
                if (v.ToUpperInvariant() == "NOAUTHNOPRIV")
                {
                    level = Levels.Reportable;
                }
                else if (v.ToUpperInvariant() == "AUTHNOPRIV")
                {
                    level = Levels.Authentication | Levels.Reportable;
                }
                else if (v.ToUpperInvariant() == "AUTHPRIV")
                {
                    level = Levels.Authentication | Levels.Privacy | Levels.Reportable;
                }
                else
                {
                    throw new ArgumentException("no such security mode: " + v);
                }
            })
                          .Add("Cn:", "Non-repeaters (default is 0)", delegate(string v) { nonRepeaters = int.Parse(v); })
                          .Add("Cr:", "Max-repetitions (default is 10)", delegate(string v) { maxRepetitions = int.Parse(v); })
                          .Add("a:", "Authentication method (MD5 or SHA)", delegate(string v) { authentication = v; })
                          .Add("A:", "Authentication passphrase", delegate(string v) { authPhrase = v; })
                          .Add("x:", "Privacy method", delegate(string v) { privacy = v; })
                          .Add("X:", "Privacy passphrase", delegate(string v) { privPhrase = v; })
                          .Add("u:", "Security name", delegate(string v) { user = v; })
                          .Add("h|?|help", "Print this help information.", delegate(string v) { showHelp = v != null; })
                          .Add("V", "Display version number of this application.", delegate(string v) { showVersion = v != null; })
                          .Add("d", "Display message dump", delegate(string v) { dump = true; })
                          .Add("t:", "Timeout value (unit is second).", delegate(string v) { timeout = int.Parse(v) * 1000; })
                          .Add("r:", "Retry count (default is 0)", delegate(string v) { retry = int.Parse(v); })
                          .Add("v:", "SNMP version (2 and 3 are currently supported)", delegate(string v)
            {
                switch (int.Parse(v))
                {
                case 2:
                    version = VersionCode.V2;
                    break;

                case 3:
                    version = VersionCode.V3;
                    break;

                default:
                    throw new ArgumentException("no such version: " + v);
                }
            });

            if (args.Length == 0)
            {
                ShowHelp(p);
                return;
            }

            List <string> extra;

            try
            {
                extra = p.Parse(args);
            }
            catch (OptionException ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }

            if (showHelp)
            {
                ShowHelp(p);
                return;
            }

            if (extra.Count < 2)
            {
                Console.WriteLine("invalid variable number: " + extra.Count);
                return;
            }

            if (showVersion)
            {
                Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
                return;
            }

            IPAddress ip;
            bool      parsed = IPAddress.TryParse(extra[0], out ip);

            if (!parsed)
            {
                foreach (IPAddress address in
                         Dns.GetHostAddresses(extra[0]).Where(address => address.AddressFamily == AddressFamily.InterNetwork))
                {
                    ip = address;
                    break;
                }

                if (ip == null)
                {
                    Console.WriteLine("invalid host or wrong IP address found: " + extra[0]);
                    return;
                }
            }

            try
            {
                List <Variable> vList = new List <Variable>();
                for (int i = 1; i < extra.Count; i++)
                {
                    Variable test = new Variable(new ObjectIdentifier(extra[i]));
                    vList.Add(test);
                }

                IPEndPoint receiver = new IPEndPoint(ip, 161);
                if (version != VersionCode.V3)
                {
                    GetBulkRequestMessage message = new GetBulkRequestMessage(0,
                                                                              version,
                                                                              new OctetString(community),
                                                                              nonRepeaters,
                                                                              maxRepetitions,
                                                                              vList);
                    ISnmpMessage response = message.GetResponse(timeout, receiver);
                    if (response.Pdu().ErrorStatus.ToInt32() != 0) // != ErrorCode.NoError
                    {
                        throw ErrorException.Create(
                                  "error in response",
                                  receiver.Address,
                                  response);
                    }

                    foreach (Variable variable in response.Pdu().Variables)
                    {
                        Console.WriteLine(variable);
                    }

                    return;
                }

                if (string.IsNullOrEmpty(user))
                {
                    Console.WriteLine("User name need to be specified for v3.");
                    return;
                }

                IAuthenticationProvider auth = (level & Levels.Authentication) == Levels.Authentication
                                                   ? GetAuthenticationProviderByName(authentication, authPhrase)
                                                   : DefaultAuthenticationProvider.Instance;

                IPrivacyProvider priv;
                if ((level & Levels.Privacy) == Levels.Privacy)
                {
                    priv = new DESPrivacyProvider(new OctetString(privPhrase), auth);
                }
                else
                {
                    priv = new DefaultPrivacyProvider(auth);
                }

                Discovery     discovery = Messenger.GetNextDiscovery(SnmpType.GetBulkRequestPdu);
                ReportMessage report    = discovery.GetResponse(timeout, receiver);

                GetBulkRequestMessage request = new GetBulkRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, new OctetString(user), nonRepeaters, maxRepetitions, vList, priv, Messenger.MaxMessageSize, report);
                ISnmpMessage          reply   = request.GetResponse(timeout, receiver);
                if (dump)
                {
                    Console.WriteLine("Request message bytes:");
                    Console.WriteLine(ByteTool.Convert(request.ToBytes()));
                    Console.WriteLine("Response message bytes:");
                    Console.WriteLine(ByteTool.Convert(reply.ToBytes()));
                }

                if (reply is ReportMessage)
                {
                    if (reply.Pdu().Variables.Count == 0)
                    {
                        Console.WriteLine("wrong report message received");
                        return;
                    }

                    var id = reply.Pdu().Variables[0].Id;
                    if (id != Messenger.NotInTimeWindow)
                    {
                        var error = id.GetErrorMessage();
                        Console.WriteLine(error);
                        return;
                    }

                    // according to RFC 3414, send a second request to sync time.
                    request = new GetBulkRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, new OctetString(user), nonRepeaters, maxRepetitions, vList, priv, Messenger.MaxMessageSize, reply);
                    reply   = request.GetResponse(timeout, receiver);
                }
                else if (reply.Pdu().ErrorStatus.ToInt32() != 0) // != ErrorCode.NoError
                {
                    throw ErrorException.Create(
                              "error in response",
                              receiver.Address,
                              reply);
                }

                foreach (Variable v in reply.Pdu().Variables)
                {
                    Console.WriteLine(v);
                }
            }
            catch (SnmpException ex)
            {
                Console.WriteLine(ex);
            }
            catch (SocketException ex)
            {
                Console.WriteLine(ex);
            }
        }
예제 #18
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry, UdpClient udpSocket /*, int retries = 0*/)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes = request.ToBytes();

            udpSocket.Connect(receiver);
            var recvTask = udpSocket.ReceiveAsync();

            if (timeout > 0)
            {
                var timeoutTask = Task.Delay(timeout);
                await udpSocket.SendAsync(bytes, bytes.Length).ConfigureAwait(false);

                var r = await Task.WhenAny(new Task[] { recvTask, timeoutTask }).ConfigureAwait(false);

                if (r == timeoutTask)
                {
                    udpSocket.Close();
                    throw TimeoutException.Create(receiver.Address, timeout);
                }
            }
            var result = await recvTask.ConfigureAwait(false);

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(result.Buffer, 0, result.Buffer.Length, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
예제 #19
0
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, CancellationToken token)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes   = request.ToBytes();
            var bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;

            // Whatever you change, try to keep the Send and the Receive close to each other.
            var buffer = new ArraySegment <byte>(bytes);
            await udpSocket.SendToAsync(buffer, SocketFlags.None, receiver ?? throw new ArgumentNullException(nameof(receiver)), token);

            int count;

            byte[] reply = new byte[bufSize];

            // IMPORTANT: follow http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx
            var      remoteAddress = udpSocket.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any;
            EndPoint remote        = new IPEndPoint(remoteAddress, 0);

            try
            {
                var result = await udpSocket.ReceiveMessageFromAsync(new ArraySegment <byte>(reply), SocketFlags.None, remote, token);

                count = result.ReceivedBytes;
            }
            catch (SocketException ex)
            {
                // IMPORTANT: Mono behavior (https://bugzilla.novell.com/show_bug.cgi?id=599488)
                if (IsRunningOnMono() && ex.SocketErrorCode == SocketError.WouldBlock)
                {
                    throw TimeoutException.Create(receiver.Address, 0);
                }

                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, 0);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
예제 #20
0
        /// <summary>
        /// Sends an  <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry, Socket udpSocket)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            SnmpType requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            byte[] bytes   = request.ToBytes();
            int    bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;

            byte[] reply = new byte[bufSize];

            // Whatever you change, try to keep the Send and the Receive close to each other.
            udpSocket.SendTo(bytes, receiver);
            udpSocket.ReceiveTimeout = timeout;
            int count;

            try
            {
                count = udpSocket.Receive(reply, 0, bufSize, SocketFlags.None);
            }
            catch (SocketException ex)
            {
                // IMPORTANT: Mono behavior.
                if (IsRunningOnMono && ex.SocketErrorCode == SocketError.WouldBlock)
                {
                    throw TimeoutException.Create(receiver.Address, timeout);
                }


                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, timeout);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            ISnmpMessage response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            SnmpType     responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                int requestId  = request.MessageId();
                int responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
예제 #21
0
파일: Discovery.cs 프로젝트: lyrain2009/gsf
 /// <summary>
 /// Converts to the bytes.
 /// </summary>
 /// <returns></returns>
 public byte[] ToBytes()
 {
     return(_discovery.ToBytes());
 }
예제 #22
0
        static void Main(string[] args)
        {
            string      community      = "public";
            bool        showHelp       = false;
            bool        showVersion    = false;
            VersionCode version        = VersionCode.V1;
            int         timeout        = 1000;
            int         retry          = 0;
            Levels      level          = Levels.Reportable;
            string      user           = string.Empty;
            string      authentication = string.Empty;
            string      authPhrase     = string.Empty;
            string      privacy        = string.Empty;
            string      privPhrase     = string.Empty;
            bool        dump           = false;

            OptionSet p = new OptionSet()
                          .Add("c:", "Community name, (default is public)", delegate(string v) { if (v != null)
                                                                                                 {
                                                                                                     community = v;
                                                                                                 }
                               })
                          .Add("l:", "Security level, (default is noAuthNoPriv)", delegate(string v)
            {
                if (v.ToUpperInvariant() == "NOAUTHNOPRIV")
                {
                    level = Levels.Reportable;
                }
                else if (v.ToUpperInvariant() == "AUTHNOPRIV")
                {
                    level = Levels.Authentication | Levels.Reportable;
                }
                else if (v.ToUpperInvariant() == "AUTHPRIV")
                {
                    level = Levels.Authentication | Levels.Privacy | Levels.Reportable;
                }
                else
                {
                    throw new ArgumentException("no such security mode: " + v);
                }
            })
                          .Add("a:", "Authentication method (MD5 or SHA)", delegate(string v) { authentication = v; })
                          .Add("A:", "Authentication passphrase", delegate(string v) { authPhrase = v; })
                          .Add("x:", "Privacy method", delegate(string v) { privacy = v; })
                          .Add("X:", "Privacy passphrase", delegate(string v) { privPhrase = v; })
                          .Add("u:", "Security name", delegate(string v) { user = v; })
                          .Add("h|?|help", "Print this help information.", delegate(string v) { showHelp = v != null; })
                          .Add("V", "Display version number of this application.", delegate(string v) { showVersion = v != null; })
                          .Add("d", "Display message dump", delegate(string v) { dump = true; })
                          .Add("t:", "Timeout value (unit is second).", delegate(string v) { timeout = int.Parse(v) * 1000; })
                          .Add("r:", "Retry count (default is 0)", delegate(string v) { retry = int.Parse(v); })
                          .Add("v:", "SNMP version (1, 2, and 3 are currently supported)", delegate(string v)
            {
                switch (int.Parse(v))
                {
                case 1:
                    version = VersionCode.V1;
                    break;

                case 2:
                    version = VersionCode.V2;
                    break;

                case 3:
                    version = VersionCode.V3;
                    break;

                default:
                    throw new ArgumentException("no such version: " + v);
                }
            });

            if (args.Length == 0)
            {
                ShowHelp(p);
                return;
            }

            List <string> extra;

            try
            {
                extra = p.Parse(args);
            }
            catch (OptionException ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }

            if (showHelp)
            {
                ShowHelp(p);
                return;
            }

            if ((extra.Count - 1) % 3 != 0)
            {
                Console.WriteLine("invalid variable number: " + extra.Count);
                return;
            }

            if (showVersion)
            {
                Console.WriteLine(Assembly.GetEntryAssembly().GetCustomAttribute <AssemblyVersionAttribute>().Version);
                return;
            }

            IPAddress ip;
            bool      parsed = IPAddress.TryParse(extra[0], out ip);

            if (!parsed)
            {
                var addresses = Dns.GetHostAddressesAsync(extra[0]);
                addresses.Wait();
                foreach (IPAddress address in
                         addresses.Result.Where(address => address.AddressFamily == AddressFamily.InterNetwork))
                {
                    ip = address;
                    break;
                }

                if (ip == null)
                {
                    Console.WriteLine("invalid host or wrong IP address found: " + extra[0]);
                    return;
                }
            }

            try
            {
                List <Variable> vList = new List <Variable>();
                for (int i = 1; i < extra.Count; i = i + 3)
                {
                    string type = extra[i + 1];
                    if (type.Length != 1)
                    {
                        Console.WriteLine("invalid type string: " + type);
                        return;
                    }

                    ISnmpData data;

                    switch (type[0])
                    {
                    case 'i':
                        data = new Integer32(int.Parse(extra[i + 2]));
                        break;

                    case 'u':
                        data = new Gauge32(uint.Parse(extra[i + 2]));
                        break;

                    case 't':
                        data = new TimeTicks(uint.Parse(extra[i + 2]));
                        break;

                    case 'a':
                        data = new IP(IPAddress.Parse(extra[i + 2]).GetAddressBytes());
                        break;

                    case 'o':
                        data = new ObjectIdentifier(extra[i + 2]);
                        break;

                    case 'x':
                        data = new OctetString(ByteTool.Convert(extra[i + 2]));
                        break;

                    case 's':
                        data = new OctetString(extra[i + 2]);
                        break;

                    case 'd':
                        data = new OctetString(ByteTool.ConvertDecimal(extra[i + 2]));
                        break;

                    case 'n':
                        data = new Null();
                        break;

                    default:
                        Console.WriteLine("unknown type string: " + type[0]);
                        return;
                    }

                    Variable test = new Variable(new ObjectIdentifier(extra[i]), data);
                    vList.Add(test);
                }

                IPEndPoint receiver = new IPEndPoint(ip, 161);
                if (version != VersionCode.V3)
                {
                    foreach (Variable variable in
                             Messenger.Set(version, receiver, new OctetString(community), vList, timeout))
                    {
                        Console.WriteLine(variable);
                    }

                    return;
                }

                if (string.IsNullOrEmpty(user))
                {
                    Console.WriteLine("User name need to be specified for v3.");
                    return;
                }

                IAuthenticationProvider auth = (level & Levels.Authentication) == Levels.Authentication
                                                   ? GetAuthenticationProviderByName(authentication, authPhrase)
                                                   : DefaultAuthenticationProvider.Instance;

                IPrivacyProvider priv;
                if ((level & Levels.Privacy) == Levels.Privacy)
                {
#if NET452
                    priv = new DESPrivacyProvider(new OctetString(privPhrase), auth);
#else
                    Console.WriteLine("DES (ECB) is not supported by .NET Core.");
                    return;
#endif
                }
                else
                {
                    priv = new DefaultPrivacyProvider(auth);
                }

                Discovery     discovery = Messenger.GetNextDiscovery(SnmpType.SetRequestPdu);
                ReportMessage report    = discovery.GetResponse(timeout, receiver);

                SetRequestMessage request = new SetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, new OctetString(user), vList, priv, Messenger.MaxMessageSize, report);
                ISnmpMessage      reply   = request.GetResponse(timeout, receiver);
                if (dump)
                {
                    Console.WriteLine("Request message bytes:");
                    Console.WriteLine(ByteTool.Convert(request.ToBytes()));
                    Console.WriteLine("Response message bytes:");
                    Console.WriteLine(ByteTool.Convert(reply.ToBytes()));
                }

                if (reply is ReportMessage)
                {
                    if (reply.Pdu().Variables.Count == 0)
                    {
                        Console.WriteLine("wrong report message received");
                        return;
                    }

                    var id = reply.Pdu().Variables[0].Id;
                    if (id != Messenger.NotInTimeWindow)
                    {
                        var error = id.GetErrorMessage();
                        Console.WriteLine(error);
                        return;
                    }

                    // according to RFC 3414, send a second request to sync time.
                    request = new SetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, new OctetString(user), vList, priv, Messenger.MaxMessageSize, reply);
                    reply   = request.GetResponse(timeout, receiver);
                }
                else if (reply.Pdu().ErrorStatus.ToInt32() != 0) // != ErrorCode.NoError
                {
                    throw ErrorException.Create(
                              "error in response",
                              receiver.Address,
                              reply);
                }

                foreach (Variable v in reply.Pdu().Variables)
                {
                    Console.WriteLine(v);
                }
            }
            catch (SnmpException ex)
            {
                Console.WriteLine(ex);
            }
            catch (SocketException ex)
            {
                Console.WriteLine(ex);
            }
        }
예제 #23
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, int timeout)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var          bytes = request.ToBytes();
            ISnmpMessage response;

            // Whatever you change, try to keep the Send and the Receive close to each other.

            // fix race condition where the gc memory was corrupted
            using (var udpClient = new UdpClient())
            {
                udpClient.DontFragment = true;
                await udpClient.SendAsync(bytes, bytes.Length, receiver);

                // ReceiveAsync is an extension method implemented in class UdpClientExtension
                // it handles the timeout behavior to avoid object dispose exception when an timeout is received
                // but also - later - a valid datagram
                UdpReceiveResult receiveTask = await udpClient.ReceiveAsync(receiver, timeout);

                byte[] reply = new byte[receiveTask.Buffer.Length];
                receiveTask.Buffer.CopyTo(reply, 0);

                // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
                response = MessageFactory.ParseMessages(reply, 0, reply.Length, registry)[0];
            }

            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
예제 #24
0
		/// <summary>
		/// Sends a response message.
		/// </summary>
		/// <param name="response">
		/// A <see cref="ISnmpMessage"/>.
		/// </param>
		/// <param name="receiver">Receiver.</param>
		public void SendResponse(ISnmpMessage response, EndPoint receiver)
		{
			if (_disposed)
			{
				throw new ObjectDisposedException(GetType().FullName);
			}            
			
			if (response == null)
			{
				throw new ArgumentNullException("response");
			}

			if (receiver == null)
			{
				throw new ArgumentNullException("receiver");
			}

			if (_disposed)
			{
				throw new ObjectDisposedException("Listener");
			}

			if (_socket == null)
			{
				return;
			}

			byte[] buffer = response.ToBytes();
# if ! SILVERLIGHT // mc++
			_socket.BeginSendTo(buffer, 0, buffer.Length, 0, receiver, null, null);
# endif

		}
예제 #25
0
        /// <summary>
        /// Sends an  <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static ISnmpMessage GetResponse(this ISnmpMessage request, int timeout, IPEndPoint receiver, UserRegistry registry, Socket udpSocket)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes   = request.ToBytes();
            var bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;
            var reply   = new byte[bufSize];

            // Whatever you change, try to keep the Send and the Receive close to each other.
            udpSocket.SendTo(bytes, receiver);
            udpSocket.ReceiveTimeout = timeout;
            int count;

            try
            {
                count = udpSocket.Receive(reply, 0, bufSize, SocketFlags.None);
            }
            catch (SocketException ex)
            {
                // FIXME: If you use a Mono build without the fix for this issue (https://bugzilla.novell.com/show_bug.cgi?id=599488), please uncomment this code.

                /*
                 * if (SnmpMessageExtension.IsRunningOnMono && ex.ErrorCode == 10035)
                 * {
                 *  throw TimeoutException.Create(receiver.Address, timeout);
                 * }
                 * // */

                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, timeout);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
예제 #26
0
        /// <summary>
        /// Sends an <see cref="ISnmpMessage"/> and handles the response from agent.
        /// </summary>
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
        /// <param name="receiver">Agent.</param>
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
        /// <param name="registry">The user registry.</param>
        /// <returns></returns>
        public static async Task <ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (udpSocket == null)
            {
                throw new ArgumentNullException(nameof(udpSocket));
            }

            if (receiver == null)
            {
                throw new ArgumentNullException(nameof(receiver));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            var requestCode = request.TypeCode();

            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
            }

            var bytes   = request.ToBytes();
            var bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;

            // Whatever you change, try to keep the Send and the Receive close to each other.
            var info = SocketExtension.EventArgsFactory.Create();

            info.RemoteEndPoint = receiver;
            info.SetBuffer(bytes, 0, bytes.Length);
            using (var awaitable1 = new SocketAwaitable(info))
            {
                await udpSocket.SendToAsync(awaitable1);
            }

            int count;
            var reply = new byte[bufSize];

            // IMPORTANT: follow http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx
            var      args   = SocketExtension.EventArgsFactory.Create();
            EndPoint remote = new IPEndPoint(IPAddress.Any, 0);

            try
            {
                args.RemoteEndPoint = remote;
                args.SetBuffer(reply, 0, bufSize);
                using (var awaitable = new SocketAwaitable(args))
                {
                    count = await udpSocket.ReceiveAsync(awaitable);
                }
            }
            catch (SocketException ex)
            {
                // FIXME: If you use a Mono build without the fix for this issue (https://bugzilla.novell.com/show_bug.cgi?id=599488), please uncomment this code.

                /*
                 * if (SnmpMessageExtension.IsRunningOnMono && ex.ErrorCode == 10035)
                 * {
                 *  throw TimeoutException.Create(receiver.Address, timeout);
                 * }
                 * // */

                if (ex.SocketErrorCode == SocketError.TimedOut)
                {
                    throw TimeoutException.Create(receiver.Address, 0);
                }

                throw;
            }

            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
            var response     = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
            var responseCode = response.TypeCode();

            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
            {
                var requestId  = request.MessageId();
                var responseId = response.MessageId();
                if (responseId != requestId)
                {
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
                }

                return(response);
            }

            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
        }
예제 #27
0
        /// <summary>
        /// Sends a response message.
        /// </summary>
        /// <param name="response">
        /// A <see cref="ISnmpMessage"/>.
        /// </param>
        /// <param name="receiver">Receiver.</param>
        public void SendResponse(ISnmpMessage response, EndPoint receiver)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            if (receiver == null)
            {
                throw new ArgumentNullException("receiver");
            }

            if (_disposed)
            {
                throw new ObjectDisposedException("Listener");
            }

            if (_socket == null)
            {
                return;
            }

            var buffer = response.ToBytes();
            try
            {
                _socket.SendTo(buffer, 0, buffer.Length, 0, receiver);
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode != SocketError.Interrupted)
                {
                    // IMPORTANT: interrupted means the socket is closed.
                    throw;
                }
            }
        }