snmpmgr.c

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <snmp.h>
#include <mgmtapi.h>

#include "snmpdefs.h"

INT _CRTAPI1 main(
    IN int  argumentCount,
    IN char *argumentVector[])
    {
    startupRoutine (argumentCount, argumentVector);

    dispatchOperation(programMode, argumentVector);

    return 0;
    }

    /******************************************************
    * This routine checks the command line parameters and issues a usage statement if there are insufficient entries.
*******************************************************/
    int startupRoutine(int argc, char *argv [])
    {
          int loop;

          programMode = 0;

          switch (argc)
          {//GET, GETNEXT, SET, WALK, TRAP
          case 2:
          {
          programMode = TRAP;
    //    printf("Program Mode is TRAP %d\n", programMode);
          break;
                   }
          case 5:
          {
          programMode = GET;
    //    printf("Program Mode is GET %d\n", programMode);
          break;
                   }
          case 6:
          {
          programMode = SET;
   //     printf("Program Mode is SET %d\n", programMode);
          break;
          }             
          default:
          {
          printf ("usage: %s <Mode> <Agent> <Community> <Object ID>
          [<Value>]\n", argv [0]);
          exit (0x01);
          }
          }

          for (loop = 0; loop < TRAP; loop++)
          {
                if (!strcmp(argv[1], operationsArray[loop]))
                {
                      programMode = loop;
                      break;
                }
          }

    //    printf("Final Program Mode is %s value %d\n", operationsArray[loop], 
    //    programMode);

      return programMode;
   }

   /*******************************************************
   * Issue the required operation
   *******************************************************/
   int dispatchOperation(int programMode, char * argumentVector[])
   {
         switch (programMode)
         {
         case GET:
         {
         doSnmpOperation(programMode, argumentVector[2], 
               argumentVector[3], argumentVector[4], NULL);
         break;
         }
         case GETNEXT:
         {
         doSnmpOperation(programMode, argumentVector[2], 
               argumentVector[3], argumentVector[4], NULL);
         break;
         }
         case WALK:
         {
         doSnmpOperation(programMode, argumentVector[2], 
               argumentVector[3], argumentVector[4], NULL);
         break;
         }
         case SET:
         {
         doSnmpOperation(programMode, argumentVector[2], 
         argumentVector[3], argumentVector[4], argumentVector[5]);
         break;
         }
         case TRAP:
         {
         doSnmpOperation(programMode, argumentVector[1], 
               NULL, NULL, NULL);
         break;
         }
         default:
         {
         printf("Unknown dispatchOperation mode\n");
         break;
         }
         }

         return 0;
   }

   /*****************************************************
   * Prepare for the user-requested operation including traps
   *******************************************************/
int prepareForOp(enum Operations reqOperation, LPSTR agentName,
            LPSTR community, char *objectIdentifier, char *objectValue)
               {
    if (reqOperation != TRAP)
    {
    allocateResources(agentName, community, objectIdentifier);
    prepareDataForOperation(reqOperation, objectValue);
    }

         return 0;
    }

    /*******************************************************
    * The following function is for a complete SNMP Agent operation. 
    * The syntax for its use is as follows:
    * (i)    reqOperation may have the value GET/SET/TRAP
    * (ii)    agentName is the IP address or DNS name of the agent
    * (iii) community is the name of the SNMP community
    * (iv)    objectIdentifier is the OID of interest
    * (v)   objectValue is the value of the OID for set operations
    *******************************************************/
    int doSnmpOperation(enum Operations reqOperation, LPSTR agentName,
             LPSTR community, char *objectIdentifier, char *objectValue)
    {
         prepareForOp(reqOperation, agentName, community, 
             objectIdentifier, objectValue);

         switch (reqOperation)
         {
         case GETNEXT:
         case GET:
         case SET:
             {
             executeRequest();
             displayMIBInstanceValue(reqOperation);
             break;
             }
         case WALK:
             {
             executeMibWalk();
             break;
             }
         case TRAP:
             {
             waitForTraps();
             break;
             }
         default:
             {
             break;
             }
         }

         return 0;
    }

    /*******************************************************
    * The following function copies the parameters into
    * the corresponding member variables. It does the following:
    * (i)    Copies the SNMP Agent name into a private data member,
    * (ii)  Copies the SNMP community name into a private data member,
    * (iii) Converts the object name into the correct OID format,
    * (iv)  Sets up the variable bindings structure 
    *******************************************************/
    int allocateResources(LPSTR agentName, 
             LPSTR community, char *objectIdentifier)
    {
         AsnObjectIdentifier reqObject;

         // Allocate space for the SNMP agent name or IP address
         SNMPAgentName = (LPSTR)SNMP_malloc(strlen(agentName) + 1);
         strcpy(SNMPAgentName, agentName);

         // Allocate space for the agent community
         SNMPCommunity = (LPSTR)SNMP_malloc(strlen(community) + 1);
         strcpy(SNMPCommunity, community);

         // Open an SNMP session
         createSNMPSession();

         // Get specified object identifiers
         variableBindings.list = NULL;
         variableBindings.len = 0;

         // Convert the OID string representation to the internal representation.
         if (!SnmpMgrStrToOid(objectIdentifier, &reqObject))
         {
             printf("Error: Invalid oid, %s, specified.\n", objectIdentifier);
             return FUNCTION_FAILED;
         }
         else
         {
             // Set up the variable bindings for the SNMP operation
             OIDstring = (LPSTR)SNMP_malloc(MAX_OID_NAME_LENGTH);
             if (!SnmpMgrOidToStr(&reqObject, &OIDstring))
             {
             printf("Error: Invalid oid, %s, returned\n", OIDstring);
             return FUNCTION_FAILED;
             }

         SNMP_free(OIDstring);

         // It is here that the size of the variable bindings needs to be 
         // decided and acted upon. The number of objects in this operation
         // is determined by the value of variableBindings.len

         // Add the required OID to the variable bindings list.
         variableBindings.len++;
         if ((variableBindings.list = (RFC1157VarBind *)SNMP_realloc(
              variableBindings.list, sizeof(RFC1157VarBind) *
               variableBindings.len)) == NULL)
        {
             printf("Error: Error allocating oid, %s.\n", objectIdentifier);
            return FUNCTION_FAILED;
         }

         variableBindings.list[variableBindings.len - 1].name =
                    reqObject; // NOTE!  structure copy
         variableBindings.list[variableBindings.len - 1].value.asnType =
                    ASN_NULL;
         }

         return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * The following function frees these parameters:
    * (i)    The SNMP Agent name,
    * (ii)  The SNMP community name,
    * (iii) The object name,
    * (iv)  The variable bindings structure 
    * (v)   The SNMP session
    *******************************************************/
    int deallocateResources()
    {
         // Free any dynamically allocated memory objects
         if(SNMPAgentName)
         {
             SNMP_free(SNMPAgentName);
             SNMPAgentName = NULL;
         }

         if(SNMPCommunity)
         {
             SNMP_free(SNMPCommunity);
             SNMPCommunity = NULL;
         }

         // Free the variable bindings that have been allocated.
         SnmpUtilVarBindListFree(&variableBindings);

         // Close the SNMP session with the remote agent
         if (!SnmpMgrClose(SNMPsession))
         {
             printf("error on SnmpMgrClose %d\n", GetLastError());
             return FUNCTION_FAILED;
         }

         return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * Prepare for the required request
    *******************************************************/
    int prepareDataForOperation(enum Operations reqOperation, 
                  unsigned char *newObjectValue)
    {
    int returnValue = FUNCTION_SUCCESS;

    switch (reqOperation)
    {
    case GET: {
         prepareGetOperation();
         break;
         }
    case GETNEXT: {
         prepareGetNextOperation();
         break;
         }
    case SET: {
         prepareSetOperation(newObjectValue);
         break;
         }
    case WALK: {
         break;
         }
    case TRAP: {
         break;
         }
    default: {
         returnValue = FUNCTION_FAILED;
         break;
         }
    }

    return returnValue;
    }

    /*******************************************************
    * Prepare for a Set request
    *******************************************************/
    int prepareSetOperation(unsigned char *newObjectValue)
    {
    requestType = ASN_RFC1157_SETREQUEST;
        
    // Request that the API carry out the desired operation.
    variableBindings.len = 1;

    /* This is not sufficiently generalized, the type needs to be 
        passed in as a parameter */
    variableBindings.list[variableBindings.len - 1].value.asnType = 
         ASN_OCTETSTRING;
    variableBindings.list[variableBindings.len - 1].value.asnValue.string.stream = 
         (unsigned char *)newObjectValue;
    variableBindings.list[variableBindings.len - 1].value.asnValue.string.length = 
         strlen((const char *)
             variableBindings.list[variableBindings.len - 1].value.asnValue.string.stream);

    return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * Prepare for a Get request
    *******************************************************/
    int prepareGetOperation()
    {
    requestType = ASN_RFC1157_GETREQUEST;
    
    return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * Prepare for a GetNext request
    *******************************************************/
    int prepareGetNextOperation()
    {
    requestType = ASN_RFC1157_GETNEXTREQUEST;
    
    return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * Create a session with a remote agent
    *******************************************************/
    int createSNMPSession()
    {
    if ((SNMPsession = SnmpMgrOpen(SNMPAgentName, SNMPCommunity, timeout, retries)) == NULL)
    {
         printf("error on SnmpMgrOpen %d\n", GetLastError());
         return FUNCTION_FAILED;
    }
    return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * Execute a MIB walk
    *******************************************************/
    int executeMibWalk()
    {
         // Walk is a common term used to indicate that all MIB variables
        // under a given OID are to be traversed and displayed. This is
        // a more complex operation requiring tests and looping in addition
        // to the steps for get/getnext above.
        AsnObjectIdentifier root;
        AsnObjectIdentifier tempOid;
        SnmpUtilOidCpy(&root, &variableBindings.list[0].name);
        requestType = ASN_RFC1157_GETNEXTREQUEST;

        while(1)
        {
            if (!SnmpMgrRequest(SNMPsession, requestType, &variableBindings,
                                &errorStatus, &errorIndex))
            {
                // The API is indicating an error.
                printf("error on SnmpMgrRequest %d\n", GetLastError());
                break;
            }
            else
            {
                // The API succeeded, errors may be indicated from the remote
                // agent. Test for end of subtree or end of MIB.
                if (errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME ||
                    SnmpUtilOidNCmp(&variableBindings.list[0].name,
                                    &root, root.idLength))
                {
                    printf("End of MIB subtree.\n\n");
                    break;
                }

                // Test for general error conditions or sucesss.
                if (errorStatus > 0)
                {
                    printf("Error: errorStatus=%d, errorIndex=%d \n",
                           errorStatus, errorIndex);

                    break;
                }
                else
                {
                    // Display resulting variable binding for this iteration.
                    char *string = NULL;
                    SnmpMgrOidToStr(&variableBindings.list[0].name, &string);
                    printf("Variable = %s\n", string);
                    if (string)
                      SNMP_free(string);

                    printf("Value    = ");
                    SnmpUtilPrintAsnAny(&variableBindings.list[0].value);
                }
            } // end if()

            // Prepare for the next iteration.  Make sure the returned oid is
            // preserved and the returned value is freed.
            SnmpUtilOidCpy(&tempOid, &variableBindings.list[0].name);

            SnmpUtilVarBindFree(&variableBindings.list[0]);

            SnmpUtilOidCpy(&variableBindings.list[0].name, &tempOid);
            variableBindings.list[0].value.asnType = ASN_NULL;

            SnmpUtilOidFree(&tempOid);

        } // end while()

        // Free the variable bindings that have been allocated.
        SnmpUtilVarBindListFree(&variableBindings);
        SnmpUtilOidFree(&root);
         
         return 0;
    }

    /*******************************************************
    * Execute the required SNMP operation
    *******************************************************/
    int executeRequest()
    {
    // Request that the API carry out the desired operation.
    if (!SnmpMgrRequest(SNMPsession, requestType, &variableBindings,
                   &errorStatus, &errorIndex))
    {
         // The API is indicating an error.
         printf("error on SnmpMgrRequest %d\n", GetLastError());
         return FUNCTION_FAILED;
    }

    return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * Display the retrieved OID instance value and type
    *******************************************************/
    int displayMIBInstanceValue(enum Operations reqOperation)
    {
    // Display the resulting variable bindings.
    UINT i;
    char *string = NULL;

    printf ("SNMP Operation Type %s\n", operationsArray[reqOperation]);
    for (i = 0; i < variableBindings.len; i++)
    {
         SnmpMgrOidToStr(&variableBindings.list[i].name, &string);
         printf("MIB Object Instance = %s\n", string);
         if (string)
         SNMP_free(string);
         printf("Type and Value = ");
         SnmpUtilPrintAsnAny(&variableBindings.list[i].value);
         // Save the value of the retrieved instance
         //retrievedInstanceValue = variableBindings.list[i].value;
    }
    
    return FUNCTION_SUCCESS;
    }

    /*******************************************************
    * Initiate the process of listening for traps
    *******************************************************/
    int waitForTraps()
    {
        // Trap handling can be done two different ways: event driven or
        // polled.  The following code illustrates the steps to use event
        // driven trap reception in a management application.
        HANDLE hNewTraps = NULL;

        if (!SnmpMgrTrapListen(&hNewTraps))
        {
            printf("error on SnmpMgrTrapListen %d\n", GetLastError());
        }
        else
        {
            printf("snmputil: listening for traps...\n");
        }

        while(1)
        {
            DWORD dwResult;

            if ((dwResult = WaitForSingleObject(hNewTraps, 0xffffffff))
                == 0xffffffff)
            {
                printf("error on WaitForSingleObject %d\n",
                       GetLastError());
            }
            else if (!ResetEvent(hNewTraps))
            {
                printf("error on ResetEvent %d\n", GetLastError());
            }
            else
            {
                AsnObjectIdentifier enterprise;
                AsnNetworkAddress   IPAddress;
                AsnInteger          genericTrap;
                AsnInteger          specificTrap;
                AsnTimeticks        timeStamp;
                RFC1157VarBindList  variableBindings;
                UINT i;
                char *string = NULL;

                while(SnmpMgrGetTrap(&enterprise, &IPAddress, &genericTrap,
                                     &specificTrap, &timeStamp, &variableBindings))
                {
                    printf("snmputil: trap generic=%d specific=%d\n",
                           genericTrap, specificTrap);
                    if (IPAddress.length == 4)
                  {
                        printf("  from -> %d.%d.%d.%d\n",
                             (int)IPAddress.stream[0], (int)IPAddress.stream[1],
                             (int)IPAddress.stream[2], (int)IPAddress.stream[3]);
                  }
                    if (IPAddress.dynamic)
                  {
                        SNMP_free(IPAddress.stream);
                    }

                    for (i = 0; i < variableBindings.len; i++)
                    {
                        SnmpMgrOidToStr(&variableBindings.list[i].name, &string);
                        printf("Variable = %s\n", string);
                        if (string)
                      SNMP_free(string);

                        printf("Value    = ");
                        SnmpUtilPrintAsnAny(&variableBindings.list[i].value);
                    } // end for()
                    printf("\n");

                    SnmpUtilOidFree(&enterprise);
                    SnmpUtilVarBindListFree(&variableBindings);
             }
             }
         } // end while()
    }