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()); }
/// <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); }
/// <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); }
/// <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); }
/// <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++
/// <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); } }
/// <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); }
/// <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); }
/// <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)); }
/// <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); }
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); }
/// <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; } } }
/// <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; } } }
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); } }
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); } }
/// <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); }
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); }
/// <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); }
/// <summary> /// Converts to the bytes. /// </summary> /// <returns></returns> public byte[] ToBytes() { return(_discovery.ToBytes()); }
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); } }
/// <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); }
/// <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 }
/// <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); }
/// <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); }