コード例 #1
0
 /// <summary>
 /// Poll SNMP for a specific oid and return a string
 /// </summary>
 /// <param name="ipAddress"></param>
 /// <param name="snmpParameters"></param>
 /// <param name="oid"></param>
 /// <returns></returns>
 private string pollStringFromSnmp(IPAddress ipAddress, IAgentParameters snmpParameters, string oid)
 {
     string[] oids = new string[] { oid };
     try
     {
         VbCollection collection = GetSnmp(ipAddress, snmpParameters, oids);
         return(collection[0].Value.ToString().Trim());
     }
     catch (Exception e)
     {
         //Console.WriteLine($"Error Fetching SNMP from: {ipAddress} ({e.Message})");
         return(null);
     }
 }
コード例 #2
0
        /// <summary>
        /// Grab SNMP VbCollection results form a array of OIDs
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="snmpParameters"></param>
        /// <param name="oids"></param>
        /// <returns></returns>
        private VbCollection GetSnmp(IPAddress ipAddress, IAgentParameters snmpParameters, IEnumerable <string> oids)
        {
            UdpTarget target = new UdpTarget(ipAddress, 161, 2000, config.Settings.SnmpRetries);
            Pdu       pdu    = new Pdu(PduType.Get);

            foreach (string oid in oids)
            {
                pdu.VbList.Add(oid);
            }
            try
            {
                SnmpPacket result;
                if (snmpParameters.Version == SnmpVersion.Ver2)
                {
                    result = (SnmpV2Packet)target.Request(pdu, snmpParameters);
                }
                else
                {
                    result = (SnmpV1Packet)target.Request(pdu, snmpParameters);
                }
                if (result != null)
                {
                    if (result.Pdu.ErrorStatus == 0)
                    {
                        return(result.Pdu.VbList);
                    }
                    else
                    {
                        throw new SnmpErrorStatusException("Snmp Error Occured", result.Pdu.ErrorStatus, result.Pdu.ErrorIndex);
                    }
                }
                else
                {
                    throw new SnmpException("Snmp returned a null value");
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
コード例 #3
0
        /// <summary>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        ///
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </summary>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <param name="responseCallback">Callback that receives the result of the async operation.</param>
        /// <returns>True if async request was successfully initiated, otherwise false.</returns>
        public bool RequestAsync(Pdu pdu, IAgentParameters agentParameters, SnmpAsyncResponse responseCallback)
        {
            if (IsBusy)
            {
                return(false);                // class is busy
            }
            _response        = null;
            _response       += responseCallback;
            _agentParameters = agentParameters;
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.AuthenticationError, null);
                    return(false);
                }
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.PrivacyError, null);
                    return(false);
                }
                _noSourceCheck = false;                 // this option is not valid for SNMP v3 requests
                ScopedPdu outPdu = new ScopedPdu(pdu);
                outPdu.ContextEngineId.Set(secparams.EngineId);
                outPdu.ContextName.Set(secparams.ContextName);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                try
                {
                    if (secparams.HasCachedKeys)
                    {
                        outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                    }
                    else
                    {
                        outPacket = packet.encode();
                    }
                }
                catch (Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return(false);
                }
            }
            else if (agentParameters.Version == (int)SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch (Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return(false);
                }
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch (Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return(false);
                }
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            if (!base.RequestAsync(_address, _port, outPacket, outPacket.Length, _timeout, _retry, new SnmpAsyncCallback(AsyncResponse)))
            {
                return(false);
            }
            return(true);
        }
コード例 #4
0
        /// <summary>Make SNMP Request</summary>
        /// <remarks>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        ///
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </remarks>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <returns>Appropriate SNMP packet class for the reply received (<see cref="SnmpV1Packet"/>,
        /// <see cref="SnmpV2Packet"/>, or <see cref="SnmpV3Packet"/>. Null value if there was an error
        /// with the request.</returns>
        /// <exception cref="SnmpAuthenticationException">Thrown on SNMPv3 requests when authentication password
        /// is not specified on authNoPriv or authPriv requests in SecureAgentParameters or if incoming packet
        /// authentication check failed.
        ///
        /// With SNMP ver1 and ver2c, authentication check fails when invalid community name is parsed in the reply.</exception>
        /// <exception cref="SnmpPrivacyException">Thrown on SNMPv3 requests when privacy password is not
        /// specified in SecureAgentParameters on authPriv requests.</exception>
        /// <exception cref="SnmpException">Thrown in following cases:
        ///
        /// * IAgentParameters.Valid() returned false. SnmpException.ErrorCode is set to SnmpException.InvalidIAgentParameters
        /// * No data received on request. SnmpException.ErrorCode is set to SnmpException.NoDataReceived
        /// * Invalid RequestId in reply. SnmpException.ErrorCode is set to SnmpException.InvalidRequestId
        /// </exception>
        public SnmpPacket Request(Pdu pdu, IAgentParameters agentParameters)
        {
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                {
                    throw new SnmpAuthenticationException("Authentication password not specified.");
                }
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                {
                    throw new SnmpPrivacyException("Privacy password not specified.");
                }
                _noSourceCheck = false;                 // this option is not valid for SNMP v3 requests
                ScopedPdu    outPdu = new ScopedPdu(pdu);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                {
                    outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                }
                else
                {
                    outPacket = packet.encode();
                }
            }
            else if (agentParameters.Version == SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                {
                    throw new SnmpException(SnmpException.InvalidIAgentParameters, "Invalid AgentParameters. Unable to process request.");
                }
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                outPacket      = packet.encode();
                _noSourceCheck = param.DisableReplySourceCheck;
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                {
                    throw new SnmpException(SnmpException.InvalidIAgentParameters, "Invalid AgentParameters. Unable to process request.");
                }
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                _noSourceCheck = param.DisableReplySourceCheck;
                outPacket      = packet.encode();
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            byte[] inBuffer = base.Request(_address, _port, outPacket, outPacket.Length, _timeout, _retry);

            if (inBuffer == null || inBuffer.Length <= 0)
            {
                throw new SnmpException(SnmpException.NoDataReceived, "No data received on request.");
            }
            // verify packet
            if (agentParameters.Version == SnmpVersion.Ver1)
            {
                SnmpV1Packet    packet = new SnmpV1Packet();
                AgentParameters param  = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return(packet);
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                SnmpV2Packet    packet = new SnmpV2Packet();
                AgentParameters param  = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return(packet);
            }
            else if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SnmpV3Packet          packet    = new SnmpV3Packet();
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                {
                    packet.decode(inBuffer, inBuffer.Length, secparams.AuthenticationKey, secparams.PrivacyKey);
                }
                else
                {
                    packet.decode(inBuffer, inBuffer.Length);
                }
                // first check if packet is a discovery response and process it
                if (packet.Pdu.Type == PduType.Report && packet.Pdu.VbCount > 0 && packet.Pdu.VbList[0].Oid.Equals(SnmpConstants.usmStatsUnknownEngineIDs))
                {
                    secparams.UpdateDiscoveryValues(packet);
                    return(packet);
                }
                else
                {
                    if (!secparams.ValidateIncomingPacket(packet))
                    {
                        return(null);
                    }
                    else
                    {
                        secparams.UpdateDiscoveryValues(packet);                         // update time, etc. values
                        return(packet);
                    }
                }
            }
            return(null);
        }
コード例 #5
0
        private System.Collections.Generic.Dictionary <string, string> SendPacket(SnmpOperationType pduType, System.Collections.Generic.List <VarBinding> variables)
        {
            if (variables == null || variables.Count < 1)
            {
                throw new System.ArgumentNullException("The variables for the " + pduType + " operation is null or empty.");
            }
            UdpTarget        udpTarget       = null;
            IAgentParameters agentParameters = null;
            Pdu pdu = null;

            System.Collections.Generic.Dictionary <string, string> result3;
            try
            {
                udpTarget = new UdpTarget(System.Net.IPAddress.Parse(this.config.AgentIp), this.config.Port, this.config.Timeout, this.config.Retry);
                if (this.config.Version == SnmpVersionType.Ver3)
                {
                    agentParameters = new SecureAgentParameters();
                    SecureAgentParameters secureAgentParameters = agentParameters as SecureAgentParameters;
                    if (!udpTarget.Discovery(secureAgentParameters))
                    {
                        throw new SnmpException("Discovery failed: The device with ip(" + this.config.AgentIp + ") is unreachable.");
                    }
                    pdu = new ScopedPdu();
                    SnmpV3Config snmpV3Config = this.config as SnmpV3Config;
                    secureAgentParameters.SecurityName.Set(snmpV3Config.UserName);
                    secureAgentParameters.Authentication = (AuthenticationDigests)snmpV3Config.Authentication;
                    secureAgentParameters.AuthenticationSecret.Set(snmpV3Config.AuthSecret);
                    secureAgentParameters.Privacy = (PrivacyProtocols)snmpV3Config.Privacy;
                    secureAgentParameters.PrivacySecret.Set(snmpV3Config.PrivacySecret);
                    secureAgentParameters.Reportable = true;
                }
                else
                {
                    if (this.config.Version == SnmpVersionType.Ver1)
                    {
                        OctetString community = new OctetString(((SnmpV1Config)this.config).Community);
                        agentParameters = new AgentParameters(SnmpVersion.Ver1, community);
                    }
                    else
                    {
                        OctetString community = new OctetString(((SnmpV2Config)this.config).Community);
                        agentParameters = new AgentParameters(SnmpVersion.Ver2, community);
                    }
                    pdu = new Pdu();
                }
                DictionaryUtil dictionaryUtil = new DictionaryUtil();
                foreach (VarBinding current in variables)
                {
                    try
                    {
                        if (current is LeafVarBinding)
                        {
                            if (pduType.Equals(SnmpOperationType.GetTable) || pduType.Equals(SnmpOperationType.Walk))
                            {
                                pdu.Type = PduType.Get;
                            }
                            else
                            {
                                pdu.Type = (PduType)pduType;
                                if (pduType.Equals(SnmpOperationType.GetBulk))
                                {
                                    this.configBulkPdu(pdu, current.MaxRepetition);
                                }
                            }
                            System.Collections.Generic.Dictionary <string, string> result = this.ReceiveResponseWithLeafVB((LeafVarBinding)current, pdu, udpTarget, agentParameters);
                            dictionaryUtil.Add(result);
                        }
                        else
                        {
                            if (agentParameters.Version == SnmpVersion.Ver1)
                            {
                                pdu.Type = PduType.GetNext;
                            }
                            else
                            {
                                pdu.Type = PduType.GetBulk;
                                this.configBulkPdu(pdu, current.MaxRepetition);
                            }
                            System.Collections.Generic.Dictionary <string, string> result2 = this.ReceiveResponseWithTableVB((TableVarBinding)current, pdu, udpTarget, agentParameters);
                            dictionaryUtil.Add(result2);
                        }
                    }
                    catch (System.Exception ex)
                    {
                        if (!ex.Message.Contains("Invalid ASN.1 type encountered 0x00. Unable to continue decoding."))
                        {
                            throw new SnmpException(ex.Message);
                        }
                    }
                }
                result3 = dictionaryUtil.Result;
            }
            catch (System.Exception ex2)
            {
                throw new SnmpException(ex2.Message);
            }
            finally
            {
                if (udpTarget != null)
                {
                    udpTarget.Close();
                }
            }
            return(result3);
        }
コード例 #6
0
        private System.Collections.Generic.Dictionary <string, string> ReceiveResponseWithTableVB(TableVarBinding tableVb, Pdu pdu, UdpTarget target, IAgentParameters param)
        {
            if (string.IsNullOrEmpty(tableVb.TableEntryOid))
            {
                throw new System.ArgumentNullException("The TableEntryOid can not be null or empty.");
            }
            Oid oid  = new Oid(tableVb.TableEntryOid);
            Oid oid2 = null;

            if (string.IsNullOrEmpty(tableVb.ColumnOid))
            {
                oid2 = (Oid)oid.Clone();
            }
            else
            {
                oid2 = new Oid(tableVb.ColumnOid);
            }
            System.Collections.Generic.Dictionary <string, string> dictionary = new System.Collections.Generic.Dictionary <string, string>();
            while (oid2 != null)
            {
                pdu.VbList.Clear();
                pdu.VbList.Add(oid2);
                SnmpPacket snmpPacket = target.Request(pdu, param);
                this.validateResponse(snmpPacket, pdu);
                foreach (Vb current in snmpPacket.Pdu.VbList)
                {
                    if (!oid.IsRootOf(current.Oid))
                    {
                        oid2 = null;
                        break;
                    }
                    if (current.Value.Type == SnmpConstants.SMI_ENDOFMIBVIEW)
                    {
                        oid2 = null;
                        break;
                    }
                    string key = current.Oid.ToString();
                    if (!dictionary.ContainsKey(key))
                    {
                        dictionary.Add(key, current.Value.ToString());
                        oid2 = current.Oid;
                    }
                }
            }
            return(dictionary);
        }
コード例 #7
0
        private System.Collections.Generic.Dictionary <string, string> ReceiveResponseWithLeafVB(LeafVarBinding leafVb, Pdu pdu, UdpTarget target, IAgentParameters param)
        {
            if (leafVb.VarBindings.Count < 1)
            {
                throw new System.ArgumentNullException("The variables for the " + pdu.Type + " opertion is emtpy.");
            }
            pdu.VbList.Clear();
            this.configPduVb(leafVb, pdu);
            SnmpPacket snmpPacket = target.Request(pdu, param);

            this.validateResponse(snmpPacket, pdu);
            System.Collections.Generic.Dictionary <string, string> dictionary = new System.Collections.Generic.Dictionary <string, string>();
            foreach (Vb current in snmpPacket.Pdu.VbList)
            {
                if (current.Value.Type != SnmpConstants.SMI_NOSUCHINSTANCE && current.Value.Type != SnmpConstants.SMI_NOSUCHOBJECT && current.Value.Type != SnmpConstants.SMI_ENDOFMIBVIEW)
                {
                    string key = current.Oid.ToString();
                    if (!dictionary.ContainsKey(key))
                    {
                        dictionary.Add(key, current.Value.ToString());
                    }
                }
            }
            return(dictionary);
        }
コード例 #8
0
ファイル: UdpTarget.cs プロジェクト: ravihuang/check_ac
        /// <summary>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        /// 
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </summary>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <param name="responseCallback">Callback that receives the result of the async operation.</param>
        /// <returns>True if async request was successfully initiated, otherwise false.</returns>
        public bool RequestAsync(Pdu pdu, IAgentParameters agentParameters, SnmpAsyncResponse responseCallback)
        {
            if (IsBusy)
            {
                return false; // class is busy
            }
            _response = null;
            _response += responseCallback;
            _agentParameters = agentParameters;
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.AuthenticationError, null);
                    return false;
                }
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.PrivacyError, null);
                    return false;
                }
                _noSourceCheck = false; // this option is not valid for SNMP v3 requests
                ScopedPdu outPdu = new ScopedPdu(pdu);
                outPdu.ContextEngineId.Set(secparams.EngineId);
                outPdu.ContextName.Set(secparams.ContextName);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                try
                {
                    if (secparams.HasCachedKeys)
                        outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                    else
                        outPacket = packet.encode();
                }
                catch( Exception ex )
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return false;
                }
            }
            else if (agentParameters.Version == (int)SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch( Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return false;
                }
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch( Exception ex )
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return false;
                }
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            if( ! base.RequestAsync(_address, _port, outPacket, outPacket.Length, _timeout, _retry, new SnmpAsyncCallback(AsyncResponse) ) ) {
                return false;
            }
            return true;
        }
コード例 #9
0
ファイル: UdpTarget.cs プロジェクト: ravihuang/check_ac
        /// <summary>Make SNMP Request</summary>
        /// <remarks>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        /// 
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </remarks>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <returns>Appropriate SNMP packet class for the reply received (<see cref="SnmpV1Packet"/>, 
        /// <see cref="SnmpV2Packet"/>, or <see cref="SnmpV3Packet"/>. Null value if there was an error
        /// with the request.</returns>
        /// <exception cref="SnmpAuthenticationException">Thrown on SNMPv3 requests when authentication password
        /// is not specified on authNoPriv or authPriv requests in SecureAgentParameters or if incoming packet 
        /// authentication check failed.
        /// 
        /// With SNMP ver1 and ver2c, authentication check fails when invalid community name is parsed in the reply.</exception>
        /// <exception cref="SnmpPrivacyException">Thrown on SNMPv3 requests when privacy password is not
        /// specified in SecureAgentParameters on authPriv requests.</exception>
        /// <exception cref="SnmpException">Thrown in following cases:
        /// 
        /// * IAgentParameters.Valid() returned false. SnmpException.ErrorCode is set to SnmpException.InvalidIAgentParameters
        /// * No data received on request. SnmpException.ErrorCode is set to SnmpException.NoDataReceived
        /// * Invalid RequestId in reply. SnmpException.ErrorCode is set to SnmpException.InvalidRequestId
        /// </exception>
        public SnmpPacket Request(Pdu pdu, IAgentParameters agentParameters)
        {
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                    throw new SnmpAuthenticationException("Authentication password not specified.");
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                    throw new SnmpPrivacyException("Privacy password not specified.");
                _noSourceCheck = false; // this option is not valid for SNMP v3 requests
                ScopedPdu outPdu = new ScopedPdu(pdu);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                    outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                else
                    outPacket = packet.encode();
            }
            else if (agentParameters.Version == SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                    throw new SnmpException(SnmpException.InvalidIAgentParameters,"Invalid AgentParameters. Unable to process request.");
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                outPacket = packet.encode();
                _noSourceCheck = param.DisableReplySourceCheck;
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                    throw new SnmpException(SnmpException.InvalidIAgentParameters, "Invalid AgentParameters. Unable to process request.");
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                _noSourceCheck = param.DisableReplySourceCheck;
                outPacket = packet.encode();
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            byte[] inBuffer = base.Request(_address, _port, outPacket, outPacket.Length, _timeout, _retry);

            if (inBuffer == null || inBuffer.Length <= 0)
            {
                return null;
            }
            // verify packet
            if (agentParameters.Version == SnmpVersion.Ver1)
            {
                SnmpV1Packet packet = new SnmpV1Packet();
                AgentParameters param = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return packet;
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                SnmpV2Packet packet = new SnmpV2Packet();
                AgentParameters param = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return packet;
            }
            else if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SnmpV3Packet packet = new SnmpV3Packet();
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                    packet.decode(inBuffer, inBuffer.Length, secparams.AuthenticationKey, secparams.PrivacyKey);
                else
                    packet.decode(inBuffer, inBuffer.Length);
                // first check if packet is a discovery response and process it
                if (packet.Pdu.Type == PduType.Report && packet.Pdu.VbCount > 0 && packet.Pdu.VbList[0].Oid.Equals(SnmpConstants.usmStatsUnknownEngineIDs))
                {
                    secparams.UpdateDiscoveryValues(packet);
                    return packet;
                }
                else
                {
                    if (!secparams.ValidateIncomingPacket(packet))
                    {
                        return null;
                    }
                    else
                    {
                        secparams.UpdateDiscoveryValues(packet); // update time, etc. values
                        return packet;
                    }
                }
            }
            return null;
        }