public async Task <ISnmpMessage?> SetV3TsmAsync <T>(IPAddress ip, string oid, int retries, int port, TimeSpan timeout, X509Certificate2 certificate, TimeSpan connectionTimeout, T setValue) { if (ip == null) { throw new ArgumentNullException(nameof(ip)); } if (string.IsNullOrWhiteSpace(oid)) { throw new ArgumentNullException(nameof(oid)); } if (!Regex.IsMatch(oid, @"^(([0-9]+)\.)+[0-9]+$")) { throw new ArgumentException(oid, nameof(oid)); } if (port <= 0) { throw new ArgumentOutOfRangeException(nameof(port), port.ToString()); } if (retries <= 0) { throw new ArgumentOutOfRangeException(nameof(retries), retries.ToString()); } if (timeout <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(timeout), timeout.ToString()); } if (connectionTimeout <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(connectionTimeout)); } if (certificate is null) { throw new ArgumentNullException(nameof(certificate)); } var startDate = DateTime.Now; var snmpType = "SET"; var snmpVersion = $"3 {SecurityModel.Tsm}"; var attempt = 0; ISnmpMessage?response = null; while (attempt < retries) { var setValueByType = setValue switch { int x => new Variable(new ObjectIdentifier(oid), new Integer32(x)), string x => new Variable(new ObjectIdentifier(oid), new OctetString(x)), IPAddress x => new Variable(new ObjectIdentifier(oid), new IP(x.ToString())), uint x => new Variable(new ObjectIdentifier(oid), new Gauge32(x)), byte[] x => new Variable(new ObjectIdentifier(oid), new OctetString(x)), _ => throw new ArgumentOutOfRangeException(nameof(setValue)), }; try { var receiver = new IPEndPoint(ip, port); var clientEndPoint = ip.AddressFamily == AddressFamily.InterNetwork ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(IPAddress.IPv6Any, 0); var vList = new List <Variable>() { setValueByType }; var chain = new X509Chain(); chain.Build(certificate); using var client = new Client(clientEndPoint); client.LoadX509Certificate(chain); client.SupportedCipherSuites.Add(TCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA); var auth = TsmAuthenticationProvider.Instance; IPrivacyProvider priv = new TsmPrivacyProvider(auth); var request = new SetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, vList, priv, Messenger.MaxMessageSize); response = await request.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false); if (response is ReportMessage) { if (response.Pdu().Variables.Count == 0) { throw new Exception("wrong report message received"); } var id = response.Pdu().Variables[0].Id; if (id != Messenger.NotInTimeWindow) { var error = id.GetErrorMessage(); throw new Exception($"ERROR: {error}"); } var request2 = new GetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, OctetString.Empty, vList, priv, Messenger.MaxMessageSize, response); response = await request2.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false); } break; } catch (Exception ex) when(ex is SnmpException || ex is SocketException || ex is OperationCanceledException || ex is System.TimeoutException) { if (ex is System.TimeoutException && ex.Message == "Could Not Connect To Server") { _Logger.LogInformation($"{ip} - DTLS failed {attempt + 1} time(s)"); } await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, ex.GetType().ToString(), ex.Message).ConfigureAwait(false); ++attempt; if (attempt >= retries) { throw; } } } if (response is null) { await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, SnmpType.Null.ToString(), null).ConfigureAwait(false); return(response); } var type = response.Pdu().TypeCode; var data = response.Pdu().ErrorStatus; await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, type.ToString(), data.ToString()).ConfigureAwait(false); return(response); }
public async Task <Variable?> GetV3TsmAsync(IPAddress ip, string oid, int retries, int port, TimeSpan timeout, X509Certificate2 certificate, TimeSpan connectionTimeout) { if (ip == null) { throw new ArgumentNullException(nameof(ip)); } if (string.IsNullOrWhiteSpace(oid)) { throw new ArgumentNullException(nameof(oid)); } if (!Regex.IsMatch(oid, @"^(([0-9]+)\.)+[0-9]+$")) { throw new ArgumentException(oid, nameof(oid)); } if (port <= 0) { throw new ArgumentOutOfRangeException(nameof(port), port.ToString()); } if (retries <= 0) { throw new ArgumentOutOfRangeException(nameof(retries), retries.ToString()); } if (timeout <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(timeout), timeout.ToString()); } if (connectionTimeout <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(connectionTimeout)); } if (certificate is null) { throw new ArgumentNullException(nameof(certificate)); } var startDate = DateTime.Now; var snmpType = "GET"; var snmpVersion = $"3 {SecurityModel.Tsm}"; var attempt = 0; IEnumerable <Variable> reply = new List <Variable>(); while (attempt < retries) { try { var receiver = new IPEndPoint(ip, port); var clientEndPoint = ip.AddressFamily == AddressFamily.InterNetwork ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(IPAddress.IPv6Any, 0); var vList = new List <Variable>() { new Variable(new ObjectIdentifier(oid)) }; var chain = new X509Chain(); chain.Build(certificate); using var client = new Client(clientEndPoint); client.LoadX509Certificate(chain); client.SupportedCipherSuites.Add(TCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA); var auth = TsmAuthenticationProvider.Instance; IPrivacyProvider priv = new TsmPrivacyProvider(auth); var request = new GetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, vList, priv, Messenger.MaxMessageSize); ISnmpMessage response = await request.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false); if (response is ReportMessage) { if (response.Pdu().Variables.Count == 0) { throw new Exception("wrong report message received"); } var id = response.Pdu().Variables[0].Id; if (id != Messenger.NotInTimeWindow) { var error = id.GetErrorMessage(); throw new Exception($"ERROR: {error}"); } // according to RFC 3414, send a second request to sync time. var request2 = new GetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, OctetString.Empty, vList, priv, Messenger.MaxMessageSize, response); response = await request2.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false); } else if (response.Pdu().ErrorStatus.ToInt32() != 0) // != ErrorCode.NoError { throw ErrorException.Create( "error in response", receiver.Address, response); } reply = response.Pdu().Variables; break; } catch (Exception ex) when(ex is SnmpException || ex is SocketException || ex is OperationCanceledException || ex is System.TimeoutException) { if (ex is System.TimeoutException && ex.Message == "Could Not Connect To Server") { _Logger.LogInformation($"{ip} - DTLS failed {attempt + 1} time(s)"); } await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, ex.GetType().ToString(), ex.Message).ConfigureAwait(false); ++attempt; if (attempt >= retries) { throw; } } } var type = string.Empty; var data = string.Empty; foreach (var res in reply) { type += res.Data.TypeCode; data += res.Data.ToString(); } await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, type, data).ConfigureAwait(false); return(reply.FirstOrDefault()); }