|
|
// wsnmp_vb.c
//
// WinSNMP VarBind Functions and helpers
// Copyright 1995-1997 ACE*COMM Corp
// Rleased to Microsoft under Contract
// Beta 1 version, 970228
// Bob Natale ([email protected])
//
// 980705 - Changed test on return from SnmpMakeVB()
// in SnmpCreateVbl() to "!= SNMPAPI_SUCCESS".
//
#include "winsnmp.inc"
BOOL IsBadReadSMIValue(smiLPCVALUE value) { if (IsBadReadPtr((LPVOID)value, sizeof(smiLPCVALUE))) return TRUE;
switch(value->syntax) { case SNMP_SYNTAX_OCTETS: case SNMP_SYNTAX_BITS: case SNMP_SYNTAX_OPAQUE: case SNMP_SYNTAX_IPADDR: case SNMP_SYNTAX_NSAPADDR: return IsBadReadPtr((LPVOID)(value->value.string.ptr), value->value.string.len);
case SNMP_SYNTAX_OID: return IsBadReadPtr((LPVOID)(value->value.oid.ptr), value->value.oid.len); } return FALSE; }
SNMPAPI_STATUS SnmpMakeVB (smiLPCOID name, smiLPCVALUE value, LPVARBIND FAR *pvb) { LPVARBIND vb; if (!(vb =(LPVARBIND)GlobalAlloc (GPTR, sizeof(VARBIND)))) return (SNMPAPI_ALLOC_ERROR); vb->next_var = NULL; vb->name.ptr = NULL; if (vb->name.len = name->len) // Deliberate assignment in conditional
{ if (name->ptr) { smiUINT32 len = vb->name.len * sizeof(smiUINT32); if (vb->name.ptr = (smiLPUINT32)GlobalAlloc (GPTR, len)) CopyMemory (vb->name.ptr, name->ptr, len); } } if (!vb->name.ptr) { FreeVarBind (vb); return (SNMPAPI_OID_INVALID); } //
if (value) { switch (value->syntax) { case SNMP_SYNTAX_OCTETS: // case SNMP_SYNTAX_BITS: -- removed per Bob Natale mail from 10/09/98
case SNMP_SYNTAX_OPAQUE: case SNMP_SYNTAX_IPADDR: case SNMP_SYNTAX_NSAPADDR: vb->value.value.string.ptr = NULL; if (vb->value.value.string.len = value->value.string.len) { // Deliberate assignment, above and below
if (!(vb->value.value.string.ptr = (smiLPBYTE)GlobalAlloc (GPTR, value->value.string.len))) { FreeVarBind (vb); return (SNMPAPI_ALLOC_ERROR); } CopyMemory (vb->value.value.string.ptr, value->value.string.ptr, value->value.string.len); } break;
case SNMP_SYNTAX_OID: vb->value.value.oid.ptr = NULL; if (vb->value.value.oid.len = value->value.oid.len) { // Deliberate assignment, above and below
smiUINT32 len = value->value.oid.len * sizeof(smiUINT32); if (!(vb->value.value.oid.ptr = (smiLPUINT32)GlobalAlloc (GPTR, len))) { FreeVarBind (vb); return (SNMPAPI_ALLOC_ERROR); } CopyMemory (vb->value.value.oid.ptr, value->value.oid.ptr, len); } break;
case SNMP_SYNTAX_NULL: case SNMP_SYNTAX_NOSUCHOBJECT: case SNMP_SYNTAX_NOSUCHINSTANCE: case SNMP_SYNTAX_ENDOFMIBVIEW: break;
case SNMP_SYNTAX_INT: //case SNMP_SYNTAX_INT32: -- it have the same value as above
vb->value.value.sNumber = value->value.sNumber; break;
case SNMP_SYNTAX_CNTR32: case SNMP_SYNTAX_GAUGE32: case SNMP_SYNTAX_TIMETICKS: case SNMP_SYNTAX_UINT32: vb->value.value.uNumber = value->value.uNumber; break;
case SNMP_SYNTAX_CNTR64: vb->value.value.hNumber = value->value.hNumber; break;
default: // Clean up the allocated VarBind structure
FreeVarBind (vb); return (SNMPAPI_SYNTAX_INVALID); } // end_switch
vb->value.syntax = value->syntax; } // end_if
else vb->value.syntax = SNMP_SYNTAX_NULL; //
*pvb = vb; return (SNMPAPI_SUCCESS); } //end_SnmpMakeVB
LPVARBIND SnmpCopyVbl (LPVARBIND VarBindFrom) { SNMPAPI_STATUS status; LPVARBIND VarBindTo; LPVARBIND VarBindToPrev; LPVARBIND VarBindNewFrom = NULL; // base VB address
DWORD count = 0; while (VarBindFrom) { status = SnmpMakeVB (&VarBindFrom->name, &VarBindFrom->value, &VarBindTo); if (status != SNMPAPI_SUCCESS) { FreeVarBindList(VarBindNewFrom); // Checks for NULL
VarBindNewFrom = NULL; SaveError (0, status); break; } if (!count) VarBindNewFrom = VarBindTo; else VarBindToPrev->next_var = VarBindTo; VarBindToPrev = VarBindTo; VarBindFrom = VarBindFrom->next_var; count++; } return (VarBindNewFrom); } // end_SnmpCopyVBL
HSNMP_VBL SNMPAPI_CALL SnmpCreateVbl (IN HSNMP_SESSION hSession, IN smiLPCOID name, IN smiLPCVALUE value) { DWORD nVbl; SNMPAPI_STATUS lError = SNMPAPI_SUCCESS; HSNMP_SESSION lSession = 0; LPVARBIND VarBindPtr = NULL; // must initialize to NULL
LPVBLS pVbl;
if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1)) { lError = SNMPAPI_SESSION_INVALID; goto ERROR_OUT; }
lSession = hSession; // save it for possible error return
if (name != NULL) { if (IsBadReadPtr((LPVOID)name, sizeof(smiOID))) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_OUT; } if (name->len != 0 && name->ptr != NULL && IsBadReadPtr((LPVOID)name->ptr, name->len)) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_OUT; } } if (value != NULL && IsBadReadSMIValue(value)) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_OUT; }
// We have a valid session at this point...
if (name != NULL && name->ptr != NULL) { lError = SnmpMakeVB (name, value, &VarBindPtr); if (lError != SNMPAPI_SUCCESS) goto ERROR_OUT; else VarBindPtr->next_var = NULL; } EnterCriticalSection (&cs_VBL); lError = snmpAllocTableEntry(&VBLsDescr, &nVbl); if (lError != SNMPAPI_SUCCESS) goto ERROR_PRECHECK; pVbl = snmpGetTableEntry(&VBLsDescr, nVbl);
pVbl->Session = hSession; pVbl->vbList = VarBindPtr; ERROR_PRECHECK: LeaveCriticalSection (&cs_VBL); if (lError == SNMPAPI_SUCCESS) return ((HSNMP_VBL) ULongToPtr(nVbl+1)); ERROR_OUT: FreeVarBind (VarBindPtr); // Hnadles NULL case
return ((HSNMP_VBL) ULongToPtr(SaveError(lSession, lError))); } // end_SnmpCreateVbl
// SnmpSetVb
SNMPAPI_STATUS SNMPAPI_CALL SnmpSetVb(IN HSNMP_VBL hVbl, IN smiUINT32 index, IN smiLPCOID name, IN smiLPCVALUE value) { DWORD nVbl = HandleToUlong(hVbl) - 1; LPVARBIND VarBindList = NULL; LPVARBIND VarBindPtr = NULL; LPVARBIND VarBindPrev = NULL; SNMPAPI_STATUS lError = 0; HSNMP_SESSION lSession = 0; smiUINT32 i; LPVBLS pVbl;
if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&VBLsDescr, nVbl)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } pVbl = snmpGetTableEntry(&VBLsDescr, nVbl);
// We have a valid session at this point...
lSession = pVbl->Session; // save it for possible error return
i = SnmpCountVbl (hVbl);
// make sure the index has a valid value
if ( index > i) // index is unsigned long => no need to test for (index < 0)
{ lError = SNMPAPI_INDEX_INVALID; goto ERROR_OUT; }
// check for valid data in 'name' parameter
if (IsBadReadPtr((LPVOID)name, sizeof(smiOID))) { // if index points to an existent varbind and the
// name parameter was not provided, take it from the
// original varbind.
if (index != 0 && name == NULL) { smiUINT32 iVar;
// look for the original varbind
for (iVar = 1, VarBindPtr = pVbl->vbList; iVar < index; iVar++, VarBindPtr = VarBindPtr->next_var);
// make name to point to that varbind name
name = &(VarBindPtr->name); } else { // either adding a value with NULL OID or specifying an
// invalid value for 'name' is an SNMPAPI_ALLOC_ERROR
lError = SNMPAPI_ALLOC_ERROR; goto ERROR_OUT; } }
// If the index is 0 then a new varbind is to be added to the list.
// If it is non-zero it references a varbind in the list.
// Except we are currently allow index = count+1 to signal add to
// accommodate FTP Software's faulty implementation as used by HP OpenView
if (!index) // Allow 0 for FTP/HP OpenView mistake
index = i+1; // But make it look like the right thing!
if (name->len != 0 && name->ptr != NULL && IsBadReadPtr((LPVOID)name->ptr, name->len)) { lError = SNMPAPI_OID_INVALID; goto ERROR_OUT; }
if (value != NULL && IsBadReadSMIValue(value)) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_OUT; }
lError = SnmpMakeVB (name, value, &VarBindPtr); if (lError != SNMPAPI_SUCCESS) goto ERROR_OUT; VarBindPrev = VarBindList = pVbl->vbList; if (index == i+1) { // Adding a VarBind
if (VarBindList) { while (VarBindList->next_var != NULL) VarBindList = VarBindList->next_var; VarBindList->next_var = VarBindPtr; } else { VarBindList = VarBindPtr; pVbl->vbList = VarBindPtr; } } else { // Updating a VarBind
for (i = 1; i < index; i++) { // Position and prepare
VarBindPrev = VarBindList; VarBindList = VarBindList->next_var; } // end_for
// Replace
VarBindPtr->next_var = VarBindList->next_var; VarBindPrev->next_var = VarBindPtr; if (index == 1) pVbl->vbList = VarBindPtr; FreeVarBind (VarBindList); } // end_else
return (index); ERROR_OUT: return (SaveError (lSession, lError)); } // end_SnmpSetVb
HSNMP_VBL SNMPAPI_CALL SnmpDuplicateVbl (IN HSNMP_SESSION hSession, IN HSNMP_VBL hVbl) { DWORD lVbl; DWORD nVbl; SNMPAPI_STATUS lError = SNMPAPI_SUCCESS; HSNMP_SESSION lSession = 0; LPVBLS pVblOld, pVblNew;
if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1)) { lError = SNMPAPI_SESSION_INVALID; goto ERROR_OUT; } // We have a valid session at this point...
lSession = hSession; // save it for possible error return
lVbl = HandleToUlong(hVbl) - 1; if (!snmpValidTableEntry(&VBLsDescr, lVbl)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } pVblOld = snmpGetTableEntry(&VBLsDescr, lVbl);
EnterCriticalSection (&cs_VBL); lError = snmpAllocTableEntry(&VBLsDescr, &nVbl); if (lError != SNMPAPI_SUCCESS) goto ERROR_PRECHECK; pVblNew = snmpGetTableEntry(&VBLsDescr, nVbl);
if (pVblOld->vbList) { // Deliberate assignment follows
if (!(pVblNew->vbList = SnmpCopyVbl (pVblOld->vbList))) { // Inherit error code from SnmpCopy Vbl
snmpFreeTableEntry(&VBLsDescr, nVbl); lError = SNMPAPI_ALLOC_ERROR; goto ERROR_PRECHECK; } } pVblNew->Session = hSession; ERROR_PRECHECK: LeaveCriticalSection (&cs_VBL); if (lError == SNMPAPI_SUCCESS) return ((HSNMP_VBL) ULongToPtr(nVbl+1)); ERROR_OUT: return ((HSNMP_VBL) ULongToPtr(SaveError(lSession, lError))); } // end_SnmpDuplicateVbl
// SnmpFreeVbl
SNMPAPI_STATUS SNMPAPI_CALL SnmpFreeVbl (IN HSNMP_VBL hVbl) { DWORD nVbl = HandleToUlong(hVbl) - 1; SNMPAPI_STATUS lError = 0; DWORD i; LPVBLS pVbl;
if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&VBLsDescr, nVbl)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } pVbl = snmpGetTableEntry(&VBLsDescr, nVbl);
EnterCriticalSection (&cs_PDU); if (PDUsDescr.Used) { for (i = 0; i < PDUsDescr.Allocated; i++) { LPPDUS pPdu = snmpGetTableEntry(&PDUsDescr, i); if (pPdu->VBL == hVbl) pPdu->VBL = 0; } } LeaveCriticalSection (&cs_PDU); EnterCriticalSection (&cs_VBL); // Free all substructures
FreeVarBindList (pVbl->vbList); // Clean VBL List
snmpFreeTableEntry(&VBLsDescr, nVbl); LeaveCriticalSection (&cs_VBL); return (SNMPAPI_SUCCESS); //
ERROR_OUT: return (SaveError (0, lError)); } // end_SnmpFreeVbl
// SnmpCountVbl
SNMPAPI_STATUS SNMPAPI_CALL SnmpCountVbl (IN HSNMP_VBL hVbl) { DWORD nVbl; smiUINT32 count; SNMPAPI_STATUS lError; LPVARBIND VarBindPtr; HSNMP_SESSION lSession = 0; LPVBLS pVbl;
if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } nVbl = HandleToUlong(hVbl) - 1; if (!snmpValidTableEntry(&VBLsDescr, nVbl)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } pVbl = snmpGetTableEntry(&VBLsDescr, nVbl);
count = 0; VarBindPtr = pVbl->vbList; lSession = pVbl->Session; while (VarBindPtr) { VarBindPtr = VarBindPtr->next_var; count++; } if (!count) // No varbinds
{ lError = SNMPAPI_NOOP; goto ERROR_OUT; } return (count); //
ERROR_OUT: return (SaveError (lSession, lError)); } // end_SnmpCountVbl
// SnmpDeleteVb
SNMPAPI_STATUS SNMPAPI_CALL SnmpDeleteVb (IN HSNMP_VBL hVbl, IN smiUINT32 index) { DWORD nVbl = HandleToUlong(hVbl) - 1; HSNMP_SESSION hSession; smiUINT32 status; smiUINT32 lError = 0; HSNMP_SESSION lSession = 0; UINT i= 0; LPVARBIND VarBindList; LPVARBIND VarBindPtr; LPVARBIND VarBindPrev; LPVBLS pVbl;
if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&VBLsDescr, nVbl)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } pVbl = snmpGetTableEntry(&VBLsDescr, nVbl);
hSession = pVbl->Session; if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1)) { lError = SNMPAPI_SESSION_INVALID; goto ERROR_OUT; } lSession = hSession; // Load for SaveError() return
status = SnmpCountVbl (hVbl); if ((!index) || (index > status)) { lError = SNMPAPI_INDEX_INVALID; goto ERROR_OUT; } EnterCriticalSection (&cs_VBL); // Following cannot be NULL due to passing above test
VarBindPtr = VarBindList = pVbl->vbList; // Deleting a VarBind
for (i = 1; i <= index; i++) { // Position
VarBindPrev = VarBindPtr; VarBindPtr = VarBindList; VarBindList = VarBindList->next_var; } // end_for
if (index == 1) { // Replace
pVbl->vbList = VarBindList; } else { // Skip
VarBindPrev->next_var = VarBindList; } // end_else
FreeVarBind (VarBindPtr); LeaveCriticalSection (&cs_VBL); return (SNMPAPI_SUCCESS); //
ERROR_OUT: return (SaveError (lSession, lError)); } // end_SnmpDeleteVb
// SnmpGetVb
SNMPAPI_STATUS SNMPAPI_CALL SnmpGetVb (IN HSNMP_VBL hVbl, IN smiUINT32 index, OUT smiLPOID name, OUT smiLPVALUE value) { DWORD nVbl = HandleToUlong(hVbl) - 1; LPVARBIND VarBindPtr; SNMPAPI_STATUS lError = 0; HSNMP_SESSION lSession = 0; smiUINT32 nLength; LPVBLS pVbl;
if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&VBLsDescr, nVbl)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } pVbl = snmpGetTableEntry(&VBLsDescr, nVbl); lSession = pVbl->Session;
if (!name && !value) { lError = SNMPAPI_NOOP; goto ERROR_OUT; }
// Test for output descriptor address validity
if ((name && IsBadWritePtr (name, sizeof(smiOID))) || (value && IsBadWritePtr (value, sizeof(smiVALUE)))) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_OUT; }
nLength = SnmpCountVbl (hVbl); if ((!index) || (index > nLength)) { lError = SNMPAPI_INDEX_INVALID; goto ERROR_OUT; } if (!(VarBindPtr = pVbl->vbList)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } // SnmpFillOidValue
for (nLength = 1; nLength < index; nLength++) VarBindPtr = VarBindPtr->next_var;
if (name != NULL) { ZeroMemory (name, sizeof(smiOID));
// Copy the name OID
if ((VarBindPtr->name.len == 0) || (VarBindPtr->name.len > MAXOBJIDSIZE)) { lError = SNMPAPI_OID_INVALID; goto ERROR_OUT; } nLength = VarBindPtr->name.len * sizeof(smiUINT32); // App must free following alloc via SnmpFreeDescriptor()
if (!(name->ptr = (smiLPUINT32)GlobalAlloc (GPTR, nLength))) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_OUT; } CopyMemory (name->ptr, VarBindPtr->name.ptr, nLength); name->len = VarBindPtr->name.len; }
if (value != NULL) { // Initialize output structure
ZeroMemory (value, sizeof(smiVALUE)); // Copy the VALUE structure
switch (VarBindPtr->value.syntax) { case SNMP_SYNTAX_OCTETS: case SNMP_SYNTAX_IPADDR: case SNMP_SYNTAX_OPAQUE: case SNMP_SYNTAX_NSAPADDR: // Do copy only if nLength is non-zero
if (nLength = VarBindPtr->value.value.string.len) // Deliberate assignment
{ // App must free following alloc via SnmpFreeDescriptor()
if (!(value->value.string.ptr = (smiLPBYTE)GlobalAlloc (GPTR, nLength))) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_PRECHECK; } CopyMemory (value->value.string.ptr, VarBindPtr->value.value.string.ptr, nLength); value->value.string.len = nLength; } break;
case SNMP_SYNTAX_OID: nLength = VarBindPtr->value.value.oid.len; if (nLength > MAXOBJIDSIZE) { lError = SNMPAPI_OID_INVALID; goto ERROR_PRECHECK; } if (nLength) { // Do copy only if nLength is non-zero
nLength *= sizeof(smiUINT32); // App must free following alloc via SnmpFreeDescriptor()
if (!(value->value.oid.ptr = (smiLPUINT32)GlobalAlloc (GPTR, nLength))) { lError = SNMPAPI_ALLOC_ERROR; goto ERROR_PRECHECK; } CopyMemory (value->value.oid.ptr, VarBindPtr->value.value.oid.ptr, nLength); value->value.oid.len = VarBindPtr->value.value.oid.len; } break;
case SNMP_SYNTAX_NULL: case SNMP_SYNTAX_NOSUCHOBJECT: case SNMP_SYNTAX_NOSUCHINSTANCE: case SNMP_SYNTAX_ENDOFMIBVIEW: // Use initialized (NULL) smiVALUE
break;
case SNMP_SYNTAX_INT: value->value.sNumber = VarBindPtr->value.value.sNumber; break;
case SNMP_SYNTAX_CNTR32: case SNMP_SYNTAX_GAUGE32: case SNMP_SYNTAX_TIMETICKS: case SNMP_SYNTAX_UINT32: value->value.uNumber = VarBindPtr->value.value.uNumber; break;
case SNMP_SYNTAX_CNTR64: value->value.hNumber = VarBindPtr->value.value.hNumber; break;
default: lError = SNMPAPI_SYNTAX_INVALID; goto ERROR_PRECHECK; } // end_switch
value->syntax = VarBindPtr->value.syntax; } return (SNMPAPI_SUCCESS); // Post-name allocation failure modes
ERROR_PRECHECK: if (name && name->ptr) { GlobalFree (name->ptr); ZeroMemory (name, sizeof(smiOID)); } if (value && value->value.string.ptr) { GlobalFree (value->value.string.ptr); ZeroMemory (value, sizeof(smiVALUE)); } ERROR_OUT: return (SaveError (lSession, lError)); } // end_SnmpGetVb
|