|
|
/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
PROVSNMP.CPP
Abstract:
Purpose: Defines the acutal "Put" and "Get" functions for the "SNMP" file provider. The syntax of the mapping string is; "TBD"
History:
TBD 4-5-96 v0.01.
--*/
#include "precomp.h"
#include "stdafx.h"
#include <wbemidl.h>
#include "impdyn.h"
// This max size just prevents the read from incrementing to the point
// where CStrings no longer work
#define MAXSIZE 0x4FFF
//SNMP specific constants
#define TIMEOUT 500
#define RETRIES 3
#define IPADDRESSSTRLEN 16
//Indexes of SNMP parameters in the provider string
#define AGENT_INX 0
#define COMMUNITY_INX 1
#define OID_INX 2
BYTE HEXCHAR[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
BOOL IsDisplayable(AsnOctetString OctetString) { BYTE *p; UINT i;
for (i=0, p=OctetString.stream; ((i<OctetString.length) && ((*p >= 0x20) && (*p <= 0x7E))); i++, p++); if (i == OctetString.length) return(TRUE); else return(FALSE); }
//***************************************************************************
//
// CImpSNMP::CImpSNMP
//
// Constructor. Only current purpose is to call its base class constructor.
//
//***************************************************************************
CImpSNMP::CImpSNMP(LPUNKNOWN pUnkOuter) : CImpDyn(pUnkOuter) { return; }
//***************************************************************************
//
// CImpSNMP::StartBatch
//
// Called at the start of a batch of gets or puts.
// Retrieve agent & community from first provider string (ignore all other)
// and open a session with this agent for SNMP requests.
//
//***************************************************************************
void CImpSNMP::StartBatch(MODYNPROP * pMo,CObject **pObj,DWORD dwListSize,BOOL bGet) { TCHAR *agentStr; //IP address as String
TCHAR *communityStr; //Community String
*pObj = NULL; generalError = 0; Session = NULL; //Reset variable binding list
variableBindings.list = NULL; variableBindings.len = 0; TCHAR * pMapString;
#ifdef UNICODE
pMapString = pMo->pProviderString; #else
pMapString = WideToNarrow(pMo->pProviderString); #endif
//Retrieve agent & community information from 1st property structure :
//Create token object and make sure it has enough tokens
CProvObj ProvObj(pMapString,MAIN_DELIM); if(ProvObj.dwGetStatus() != WBEM_NO_ERROR) { generalError = ProvObj.dwGetStatus(); return; }
if(ProvObj.iGetNumTokens() < iGetMinTokens()) { generalError = M_MISSING_INFORMATION; return; } //Provider string seems OK -
//Extract agent address & community name and open SNMP session with agent
agentStr = new TCHAR[lstrlen(ProvObj.sGetToken(AGENT_INX))+1]; //(TCHAR *)CoTaskMemAlloc(lstrlen(ProvObj.sGetToken(AGENT_INX))+1);
if (agentStr == NULL) { generalError = WBEM_E_OUT_OF_MEMORY; return; } lstrcpy(agentStr, ProvObj.sGetToken(AGENT_INX));
communityStr = new TCHAR[lstrlen(ProvObj.sGetToken(COMMUNITY_INX))+1]; //(TCHAR *)CoTaskMemAlloc(lstrlen(ProvObj.sGetToken(COMMUNITY_INX)));
if (communityStr == NULL) { generalError = WBEM_E_OUT_OF_MEMORY; delete agentStr; //CoTaskMemFree(agentStr);
return; } lstrcpy(communityStr, ProvObj.sGetToken(COMMUNITY_INX));
Session = SnmpMgrOpen(agentStr, communityStr, TIMEOUT, RETRIES); if (Session == NULL) //error
{ generalError = GetLastError(); delete agentStr; delete communityStr; //CoTaskMemFree(agentStr); CoTaskMemFree(communityStr);
return; }
//Set requestType value
requestType = (bGet ? ASN_RFC1157_GETREQUEST : ASN_RFC1157_SETREQUEST);
//Free allocated buffers for agent & community - not needed once the session is open
delete agentStr; delete communityStr; //CoTaskMemFree(agentStr); CoTaskMemFree(communityStr);
//Free pMapString
#ifndef UNICODE
if(pMapString) CoTaskMemFree(pMapString); #endif
return; }
//***************************************************************************
//
// CImpSNMP::EndBatch
//
// Called at the end of a batch of gets or puts.
// At this point we should have a valid session open and a variable binding
// constructed. If so, send the SNMP request, and after receiving the answer
// close the session with this agent.
//
//***************************************************************************
void CImpSNMP::EndBatch(MODYNPROP *pMo,CObject *pObj,DWORD dwListSize,BOOL bGet) { AsnInteger errorStatus; AsnInteger errorIndex; DWORD reqCnt; DWORD varBindCnt; DWORD allocatedLength;
//temps to hold values for conversion
AsnObjectSyntax *SNMPValue; BYTE *OLESMValue;
if ((Session == NULL) || (generalError != 0)) return; //Carry out request
if (!SnmpMgrRequest(Session, requestType, &variableBindings, &errorStatus, &errorIndex)) //API error occured
generalError = GetLastError();
varBindCnt = 0; for (reqCnt = 0; reqCnt < dwListSize; reqCnt++, pMo++) { //if request failed above, need to set all dwResults to the failure code
if (generalError != 0) { pMo->dwResult = generalError; continue; } //if dwResult was already set to an error, this request was not sent in the SNMP message
// in the first place, so skip to the next one
if (pMo->dwResult != WBEM_NO_ERROR) continue;
if (errorStatus != SNMP_ERRORSTATUS_NOERROR) { //There was an SNMP error - no values are returned
pMo->pPropertyValue = NULL; pMo->dwResult = WBEM_E_FAILED; //should I return specific SNMP error ?????
//the errorIndex information is lost here !!!!
continue; }
//Value is valid - try converting to supported types
SNMPValue = &(variableBindings.list[varBindCnt].value); generalError = CopySNMPValToOLESMVal(SNMPValue, &OLESMValue, pMo->dwType, &allocatedLength); if (generalError != 0) { //error detected when converting types
pMo->pPropertyValue = NULL; pMo->dwBufferSize = 0; pMo->dwResult = generalError; } else { //types converted OK, so OLESMValue is pointing to the newly allocated value
pMo->pPropertyValue = OLESMValue; pMo->dwBufferSize = allocatedLength; pMo->dwResult = WBEM_NO_ERROR; }
varBindCnt++; }//for
//Free variable bindings structure
if (variableBindings.list != NULL) CoTaskMemFree(variableBindings.list);
//Close session with agent (don't check status since we can't return error anyway....????)
SnmpMgrClose(Session);
return;
}//EndBatch
//***************************************************************************
//
// CImpSNMP::GetProp
//
// Builds a variable binding for the current property
//
//***************************************************************************
void CImpSNMP::GetProp(MODYNPROP * pMo, CProvObj & ProvObj,CObject * pPackage) { TCHAR * oidStr; AsnObjectIdentifier reqObject; pMo->dwResult = WBEM_NO_ERROR; //To be checked in EndBatch()
//If Session is not open - error !
if ((Session == NULL) || (generalError != 0)) { pMo->dwResult = generalError; return; }
//Extract OID of property from provider string
oidStr = new TCHAR[lstrlen(ProvObj.sGetToken(OID_INX))+1]; //(TCHAR *)CoTaskMemAlloc(lstrlen(ProvObj.sGetToken(OID_INX)));
if (oidStr == NULL) { pMo->dwResult = WBEM_E_OUT_OF_MEMORY; return; } lstrcpy(oidStr, ProvObj.sGetToken(OID_INX)); //oid is the 3rd parameter in the provider string
//Convert string representation of OID to internal rep.
if (!SnmpMgrStrToOid(oidStr, &reqObject)) { pMo->dwResult = M_MISSING_INFORMATION; delete oidStr; //CoTaskMemFree(oidStr);
return; }
//If conversion successful, free OID string - not needed once we have the OID in internal rep.
delete oidStr; //CoTaskMemFree(oidStr);
//Allocate new variable binding in list
variableBindings.list = (RFC1157VarBind *)CoTaskMemRealloc(variableBindings.list, sizeof(RFC1157VarBind) * (variableBindings.len+1)); if (variableBindings.list == NULL) //allocation failed
{ pMo->dwResult = WBEM_E_OUT_OF_MEMORY; return; }
//if allocation succesful, copy info to new variable binding
variableBindings.len++; variableBindings.list[variableBindings.len - 1].name = reqObject; //structure copy !!
variableBindings.list[variableBindings.len - 1].value.asnType = ASN_NULL; return; }//GetProp
//***************************************************************************
//
// CImpSNMP::SetProp
//
// Writes the value of a single property
//
//***************************************************************************
void CImpSNMP::SetProp(MODYNPROP * pMo, CProvObj & ProvObj,CObject * pPackage) { CString sString; sString = ProvObj.sGetToken(0); pMo->dwResult = 0 ; return; }
//***************************************************************************
//
// CImpSNMP::CopySNMPValToOLESMVal
//
// Converts an SNMP value to an OLESM supported type, allocates and sets
// the value in the property structure.
// The pLen parameter outputs the length of the allocated memory
// The return value specifies the outcome of the function (0 for success)
//
//***************************************************************************
DWORD CImpSNMP::CopySNMPValToOLESMVal(AsnAny *fromVal, BYTE **pToVal, DWORD OLESMType, DWORD *pLen) { DWORD ret = WBEM_NO_ERROR; UINT i; BYTE *pSrc, *pDst;
switch (OLESMType) { case M_TYPE_DWORD : if ((fromVal->asnType == ASN_INTEGER) || (fromVal->asnType == ASN_RFC1155_COUNTER) || (fromVal->asnType == ASN_RFC1155_GAUGE) || (fromVal->asnType == ASN_RFC1155_TIMETICKS)) { if (!(*pToVal = (BYTE *)CoTaskMemAlloc(sizeof(DWORD)))) ret = WBEM_E_OUT_OF_MEMORY; else { //allocation succeeded
*pLen = sizeof(DWORD); switch (fromVal->asnType) { case ASN_INTEGER : *(DWORD *)(*pToVal) = fromVal->asnValue.number; break; case ASN_RFC1155_COUNTER : *(DWORD *)(*pToVal) = fromVal->asnValue.counter; break; case ASN_RFC1155_GAUGE : *(DWORD *)(*pToVal) = fromVal->asnValue.gauge; break; case ASN_RFC1155_TIMETICKS : *(DWORD *)(*pToVal) = fromVal->asnValue.ticks; break; default : break; } } } else ret = M_TYPE_MISMATCH; break;
case M_TYPE_LPSTR : switch (fromVal->asnType) { case ASN_OCTETSTRING : if (IsDisplayable(fromVal->asnValue.string)) //Need to add '\0' only
if (!(*pToVal = (BYTE *)CoTaskMemAlloc(fromVal->asnValue.string.length+1))) ret = WBEM_E_OUT_OF_MEMORY; else { //allocation succeeded
*pLen = fromVal->asnValue.string.length+1; memcpy(*pToVal, fromVal->asnValue.string.stream, fromVal->asnValue.string.length); *(*pToVal + (*pLen-1)) = '\0'; } else //String is stream of bytes (non-displayable)
//Need to copy non-displayable characters to "^XX" format
//Allocate 3 chars for every byte in the stream + '\0'
if (!(*pToVal = (BYTE *)CoTaskMemAlloc((fromVal->asnValue.string.length * 3) + 1))) ret = WBEM_E_OUT_OF_MEMORY; else { //allocation succeeded
*pLen = (fromVal->asnValue.string.length * 3) + 1; for (i=0, pSrc=fromVal->asnValue.string.stream, pDst=*pToVal; i<fromVal->asnValue.string.length; i++, pSrc++) { *(pDst++) = '^'; *(pDst++) = HEXCHAR[(*pSrc & 0x0F)]; *(pDst++) = HEXCHAR[((*pSrc & 0xF0) >> 4)]; } *(*pToVal + (*pLen-1)) = '\0'; }
break; case ASN_OBJECTIDENTIFIER : { TCHAR *oidStr = NULL; SnmpMgrOidToStr(&(fromVal->asnValue.object), &oidStr); if (!oidStr) ret = WBEM_E_OUT_OF_MEMORY; else { if (!(*pToVal = (BYTE *)CoTaskMemAlloc(lstrlen(oidStr)+1))) ret = WBEM_E_OUT_OF_MEMORY; else { *pLen = lstrlen(oidStr)+1; memcpy(*pToVal, oidStr, *pLen); } GlobalFree(oidStr); } } break; case ASN_SEQUENCE : if (!(*pToVal = (BYTE *)CoTaskMemAlloc(fromVal->asnValue.sequence.length))) ret = WBEM_E_OUT_OF_MEMORY; else { *pLen = fromVal->asnValue.sequence.length; memcpy(*pToVal, fromVal->asnValue.sequence.stream, fromVal->asnValue.sequence.length); } break; case ASN_RFC1155_IPADDRESS : //allocate a string for string representation of IP address
if (!(*pToVal = (BYTE *)CoTaskMemAlloc(IPADDRESSSTRLEN))) ret = WBEM_E_OUT_OF_MEMORY; else { //allocation succeeded
//Copy IP address to formatted string
sprintf((TCHAR *)*pToVal, "%u.%u.%u.%u\0", *(fromVal->asnValue.address.stream), *(fromVal->asnValue.address.stream+1), *(fromVal->asnValue.address.stream+2), *(fromVal->asnValue.address.stream+3)); *pLen = lstrlen((TCHAR *)*pToVal)+1; //*pLen = fromVal->asnValue.address.length;
//memcpy(*pToVal, fromVal->asnValue.address.stream, fromVal->asnValue.address.length);
} break; case ASN_RFC1155_OPAQUE : if (!(*pToVal = (BYTE *)CoTaskMemAlloc(fromVal->asnValue.arbitrary.length))) ret = WBEM_E_OUT_OF_MEMORY; else { *pLen = fromVal->asnValue.arbitrary.length; memcpy(*pToVal, fromVal->asnValue.arbitrary.stream, fromVal->asnValue.arbitrary.length); } break; default : ret = M_TYPE_MISMATCH; break; } break; default : ret = M_TYPE_NOT_SUPPORTED; break; }//switch (OLESMType)
if (ret != WBEM_NO_ERROR) //error
{ *pToVal = NULL; *pLen = 0; }
return(ret);
}//CopySNMPValToOLESMVal()
|