using System;
using System.Net;
using SnmpSharpNet;
// Based on snmpshart for .Net
// http://www.snmpsharpnet.com
namespace snmpsharpget
{
    class Program
    {
        static void Main(string[] args)
        {
            string oid = "";
            string ip = "";
            int port = 161;
            string securityuser = "";
            string authenticationdigest = "";
            AuthenticationDigests authDigest = AuthenticationDigests.None;
            string authenticationpassword = "";
            PrivacyProtocols privacyprotocol = PrivacyProtocols.None;
            string privacyprotocolstring = "";
            string privacyprotocolpassword = "";
            string community = "";
            int version = -1;
            SnmpV3Packet result3;
            SnmpV1Packet result1;
            SnmpV2Packet result2;
            VbCollection vbCollection = null;
            int ErrorStatus = -1;
            int ErrorIndex = -1;
            if (args.Length == 0)
            {
                Console.WriteLine("Specify arguments:\r\n" +
                "-v:version (Example: -v:1,-v:2c, -v:3)\r\n" +
                "-r:IP (Example: -r:192.168.1.0)\r\n" +
                "-p:port (Optional, default 161, example: -p:555\r\n" +
                "-o:OID (Example: -o:1.3.6.1.2.1.1.2.0" +
                "-c:community_string (Example: -c:public)\r\n" +
                "-ap:AuthenticationDigest SHA/MD5(Example: -ap:SHA)\r\n" +
                "-aw:AuthenticationPassword\r\n" +
                "-pp:PrivacyProtocol DES/AES128/AES192/AES256/TripleDES (Example: -pp:AES128)\r\n" +
                "-pp:PrivacyPassword\r\n" +
                "-sn:SecurityName");
                return;
            }
            else
            {
                foreach (string arg in args)
                {
                    if (arg.IndexOf("-v:") == 0)
                    {
                        if (arg.Substring(3) == "1")
                            version = 1;
                        if (arg.Substring(3) == "2c")
                            version = 2;
                        if (arg.Substring(3) == "3")
                            version = 3;
                    }
                    if (arg.IndexOf("-o:") == 0)
                    {
                        oid = arg.Substring(3);
                    }
                    if (arg.IndexOf("-r:") == 0)
                    {
                        ip = arg.Substring(3);
                    }
                    if (arg.IndexOf("-sn:") == 0)
                    {
                        securityuser = arg.Substring(4);
                    }
                    if (arg.IndexOf("-c:") == 0)
                    {
                        community = arg.Substring(3);
                    }
                    if (arg.IndexOf("-p:") == 0)
                    {
                        string ports = arg.Substring(3);
                        try
                        {
                            port = Int32.Parse(ports);
                        }
                        catch (Exception ex)
                        {
                            port = -1;
                            Console.WriteLine("Not correct port value: " + ports);
                            break;
                        }
                    }
                    if (arg.IndexOf("-ap:") == 0)
                    {
                        authenticationdigest = arg.Substring(4);
                        if (String.Compare(authenticationdigest, "SHA", true) == 0)
                            authDigest = AuthenticationDigests.SHA1;
                        if (String.Compare(authenticationdigest, "MD5", true) == 0)
                            authDigest = AuthenticationDigests.MD5;
                    }
                    if (arg.IndexOf("-aw:") == 0)
                    {
                        authenticationpassword = arg.Substring(4);
                    }
                    if (arg.IndexOf("-pp:") == 0)
                    {
                        privacyprotocolstring = arg.Substring(4);
                        if (String.Compare(privacyprotocolstring, "DES", true) == 0)
                            privacyprotocol = PrivacyProtocols.DES;
                        if (String.Compare(privacyprotocolstring, "AES128", true) == 0)
                            privacyprotocol = PrivacyProtocols.AES128;
                        if (String.Compare(privacyprotocolstring, "AES192", true) == 0)
                            privacyprotocol = PrivacyProtocols.AES192;
                        if (String.Compare(privacyprotocolstring, "AES256", true) == 0)
                            privacyprotocol = PrivacyProtocols.AES256;
                        if (String.Compare(privacyprotocolstring, "TripleDES", true) == 0)
                            privacyprotocol = PrivacyProtocols.TripleDES;
                    }
                    if (arg.IndexOf("-pw:") == 0)
                    {
                        privacyprotocolpassword = arg.Substring(4);
                    }
                }
            }
            if (port == -1)
            {
                Console.WriteLine("Not valid port: " + port.ToString());
                return;
            }
            if ((version < 1) || (version>3))
            {
                Console.WriteLine("Not valid version: ");
                return;
            }

            UdpTarget target = null;
            try
            {
                IpAddress ipa = new IpAddress(ip);
                target = new UdpTarget((IPAddress)ipa);
                target.Port = port;
                // Construct a Protocol Data Unit (PDU)
                Pdu pdu = new Pdu(PduType.Get);
                // Set the request type (default is Get)
                // pdu.Type = PduType.Get;
                // Add variables you wish to query
                pdu.VbList.Add(oid); //oid);

                if (version == 3)
                {
                    SecureAgentParameters param = new SecureAgentParameters();
                    if (!target.Discovery(param))
                    {
                        Console.WriteLine("Discovery failed. Unable to continue...");
                        target.Close();
                        return;
                    }
                    if (privacyprotocol != PrivacyProtocols.None)
                    {
                        param.authPriv(securityuser,
                               authDigest, authenticationpassword,
                               privacyprotocol, privacyprotocolpassword);
                    }
                    else
                    {
                        if (authDigest != AuthenticationDigests.None)
                        {
                            param.Privacy = PrivacyProtocols.None;
                            param.authNoPriv(securityuser, authDigest, authenticationpassword);
                        }
                        else
                        {
                            param.Privacy = PrivacyProtocols.None;
                            param.Authentication = AuthenticationDigests.None;
                            param.noAuthNoPriv(securityuser);
                        }
                    }
                    // Make a request. Request can throw a number of errors so wrap it in try/catch
                    try
                    {
                        result3 = (SnmpV3Packet)target.Request(pdu, param);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Error: {0}", ex.Message);
                        result3 = null;
                    }
                    if (result3 != null)
                    {
                        if (result3.ScopedPdu.Type == PduType.Report)
                        {
                            Console.WriteLine("SNMPv3 report:");
                            foreach (Vb v in result3.ScopedPdu.VbList)
                            {
                                Console.WriteLine("Oid:{0}\r\nType: {1}\r\nValue: {2}",
                                  v.Oid.ToString(),
                                  SnmpConstants.GetTypeName(v.Value.Type), v.Value.ToString());
                            }
                        }
                        else
                        {
                            if (result3.ScopedPdu.ErrorStatus == 0)
                            {
                                foreach (Vb v in result3.ScopedPdu.VbList)
                                {
                                    Console.WriteLine("OID={0}\r\nType={1}\r\nValue:{2}",
                                      v.Oid.ToString(),
                                      SnmpConstants.GetTypeName(v.Value.Type), v.Value.ToString());
                                }
                            }
                            else
                            {
                                Console.WriteLine("SNMPError: {0} ({1}): {2}",
                                  SnmpError.ErrorMessage(result3.ScopedPdu.ErrorStatus),
                                  result3.ScopedPdu.ErrorStatus, result3.ScopedPdu.ErrorIndex);
                            }
                        }
                    }
                }
                else
                {
                    OctetString communityOctet = new OctetString(community);
                    AgentParameters param = new AgentParameters(communityOctet);
                    if (version == 1)
                    {
                        param.Version = SnmpVersion.Ver1;
                        result1 = (SnmpV1Packet)target.Request(pdu, param);
                        vbCollection = result1.Pdu.VbList;
                        ErrorStatus = result1.Pdu.ErrorStatus;
                        ErrorIndex = result1.Pdu.ErrorIndex;
                    }
                    else
                    {
                        param.Version = SnmpVersion.Ver2;
                        result2 = (SnmpV2Packet)target.Request(pdu, param);
                        vbCollection = result2.Pdu.VbList;
                        ErrorStatus = result2.Pdu.ErrorStatus;
                        ErrorIndex = result2.Pdu.ErrorIndex;
                    }
                    if (ErrorStatus != 0)
                    {
                        // agent reported an error with the request
                        Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
                            ErrorStatus, ErrorIndex);
                    }
                    else
                    {
                        if (vbCollection != null)
                        {
                            foreach (Vb v in vbCollection)
                            {
                                Console.WriteLine("OID={0}\r\nType={1}\r\nValue:{2}",
                                  v.Oid.ToString(),
                                  SnmpConstants.GetTypeName(v.Value.Type), v.Value.ToString());
                            }
                        }
                    }
                }
                target.Close();
            }
            catch (Exception ex)
            {
                if (target != null)
                    target.Close();
                Console.WriteLine("Exception: " + ex.Message + " type: " + ex.GetType().ToString() );
            }
        }
    }
}