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()
}