// SNMPv1.cpp : Implementation of CSNMPv1 #include #include #include #include #include #include #include "stdafx.h" #include "NetMgr.h" #include "SNMPv1.h" ///////////////////////////////////////////////////////////////////////////// // CSNMPv1 STDMETHODIMP CSNMPv1::Open(VARIANT agent, VARIANT community, int timeout, int retries, BSTR *statusCode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()) // Local Variable Declarations char lcAgent[255]; char lcCommunity[255]; // Convert variant into char by using %ls format type sprintf(lcAgent,"%ls", agent.bstrVal); sprintf(lcCommunity, "%ls", community.bstrVal); // Open a "session" to the agent and verify if a connection could be opened if ((session = SnmpMgrOpen(lcAgent, lcCommunity, timeout, retries)) == NULL) { lpVal = "Session could not be opened successfully"; } else { lpVal = "Session opened successfully"; } // Set return value lpVal.SetSysString(statusCode); return S_OK; } STDMETHODIMP CSNMPv1::Close(int *statusCode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()) // Test to see if the session can be successfully closed if (!SnmpMgrClose(session)) { statusCode = (int *)1; } else { statusCode = (int *)0; } return S_OK; } STDMETHODIMP CSNMPv1::Get(VARIANT oidStr, BSTR* value) { AFX_MANAGE_STATE(AfxGetStaticModuleState()) // Local variable declarations -- P1 RFC1157VarBindList vb; // Variable Binding List; Binds OID to value AsnObjectIdentifier objID; // The actual OID itself AsnInteger errorStatus; // Error type that is returned if encountered AsnInteger errorIndex; // Works with variable above AsnAny* pAny2; // Struct that is used in conjunction with // the vb variable // Local variable declarations -- P2 char asciiStr[255]; // utility variable char lcOIDStr[255]; // local char reference to the oidStr parameter int ret, intBuf, i; // used for return values, counters, etc. // Convert variant to char sprintf(lcOIDStr, "%ls", oidStr.bstrVal); // Get oid's... vb.list = NULL; vb.len = 0; // Convert the string OID to teh AsnObjectIdentifier data type ret = SnmpMgrStrToOid((LPSTR)lcOIDStr, &objID); // Since sucessfull, add to the variable bindings list. vb.len++; if ((vb.list = (RFC1157VarBind *)SNMP_realloc(vb.list, sizeof(RFC1157VarBind) *vb.len)) == NULL) { lpVal = "Error: Error allocating oid"; lpVal.SetSysString(value); return S_OK; } // Assigning OID to variable bindings list vb.list[0].name = objID; vb.list[0].value.asnType = ASN_NULL; // Make request to agent if (!SnmpMgrRequest(session, ASN_RFC1157_GETREQUEST, &vb, &errorStatus, &errorIndex)) { sprintf(asciiStr,"Error: SnmpMgrRequest could not carry out desired option (Error %d -- %s)", errorStatus, oidStr); lpVal = (LPSTR)asciiStr; lpVal.SetSysString(value); } else { // Validate that no error exists if (errorStatus > 0) { lpVal = "Error: Error with Agent process"; lpVal.SetSysString(value); } else { // Assign variable binding return value to pAny2 // I explicity split every asn type so that if further // logic was needed it could be easily implemented pAny2 = &vb.list[0].value; switch (pAny2->asnType) { case ASN_OCTETSTRING: // What are we dealing with? if ((pAny2->asnValue.string.stream[0] >> 4) > 0) { // Loop through the Octet stream for (i=0; i < pAny2->asnValue.string.length; i++) { intBuf += sprintf(asciiStr + intBuf,"%c",pAny2->asnValue.string.stream[i]); } } else { // Loop through the Octet stream for (i=0; i < pAny2->asnValue.string.length; i++) { intBuf += sprintf(asciiStr + intBuf,"%02x",pAny2->asnValue.string.stream[i]); } } break; case ASN_INTEGER32: sprintf(asciiStr,"%d",pAny2->asnValue.number); break; case ASN_TIMETICKS: sprintf(asciiStr,"%d",pAny2->asnValue.ticks); break; case ASN_GAUGE32: sprintf(asciiStr,"%u",pAny2->asnValue.gauge); break; case ASN_COUNTER32: sprintf(asciiStr,"%u",pAny2->asnValue.counter); break; case ASN_IPADDRESS: sprintf(asciiStr, "%d.%d.%d.%d", pAny2->asnValue.address.stream[0], pAny2->asnValue.address.stream[1], pAny2->asnValue.address.stream[2], pAny2->asnValue.address.stream[3]); break; case ASN_OBJECTIDENTIFIER: for (i=0; i < pAny2->asnValue.object.idLength; i++) { intBuf += sprintf(asciiStr + intBuf,".%u",pAny2->asnValue.object.ids[i]); } break; case ASN_OPAQUE: for (i=0; i < pAny2->asnValue.arbitrary.length; i++) { intBuf += sprintf(asciiStr + intBuf,"%02X ",pAny2->asnValue.arbitrary.stream[i]); } break; case ASN_NULL: break; } // Set response with value from agent lpVal = (LPSTR)asciiStr; lpVal.SetSysString(value); } } // Release variable binding list SnmpUtilVarBindListFree(&vb); return S_OK; } STDMETHODIMP CSNMPv1::Set(VARIANT oidStr, VARIANT value, BSTR *statusCode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()) // Local variable definitions RFC1157VarBindList vb; // Variable Binding List; Binds OID to value AsnObjectIdentifier objID; // The actual OID itself AsnInteger errorStatus; // Error type that is returned if encountered AsnInteger errorIndex; // Works with variable above int ret; char tcVar[255], lcOIDStr[255]; // Convert variant to char by using format type sprintf(lcOIDStr, "%ls", oidStr.bstrVal); // Get oid's... vb.list = NULL; vb.len = 0; // Convert the string OID to teh AsnObjectIdentifier data type ret = SnmpMgrStrToOid(lcOIDStr, &objID); // Since sucessfull, add to the variable bindings list. vb.len++; if ((vb.list = (RFC1157VarBind *)SNMP_realloc(vb.list, sizeof(RFC1157VarBind) *vb.len)) == NULL) { lpVal = "Bind Error"; lpVal.SetSysString(statusCode); return S_OK; } // Assign OID to variable binding list vb.list[vb.len - 1].name = objID; // Test to see if we're dealing with an integer or a string if (value.vt == 2 || value.vt == 3) { // Integer -- assign value.intVal vb.list[vb.len - 1].value.asnType = ASN_INTEGER32; vb.list[vb.len - 1].value.asnValue.number = value.lVal; } else { // String -- things are more complex here // First let's define the asn type vb.list[vb.len - 1].value.asnType = ASN_OCTETSTRING; // Nify little trick huh? ls is a wide character string // format type sprintf(tcVar,"%ls",value.bstrVal); // Next we set the string length (remember to add 1 for \0) vb.list[vb.len - 1].value.asnValue.string.length = strlen(tcVar) + 1; // From here we basically allocate an empty string into the stream vb.list[vb.len - 1].value.asnValue.string.stream = (unsigned char*)malloc(vb.list[vb.len - 1].value.asnValue.string.length); // then we copy the string from tcVar into stream // (NOTE: All empty spaces are trim'd off) strcpy((char *)vb.list[vb.len - 1].value.asnValue.string.stream, tcVar); // Set dynamic to false because we're specifying a length vb.list[vb.len - 1].value.asnValue.string.dynamic = FALSE; } // And Viola!! We've got ourselves a SNMP Set command that can handle // Integer and String! // Preset lpVal so that we don't have to duplicate code lpVal = "Successful"; // Request that the API carry out the desired operation. if (!SnmpMgrRequest(session, ASN_RFC1157_SETREQUEST, &vb, &errorStatus, &errorIndex)) { // The API is indicating an error. lpVal = "Agent Request Error"; } else { // The API succeeded, errors may be indicated from the remote // agent. if (errorStatus > 0) { sprintf(tcVar,"API Error : %d", errorStatus); lpVal = (LPSTR)tcVar; } } // Release variable binding list SnmpUtilVarBindListFree(&vb); // Set response lpVal.SetSysString(statusCode); return S_OK; }