Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

659 lines
17 KiB

// wsnmp_ut.c
//
// WinSNMP Utility Functions and helpers
// Copyright 1995-1997 ACE*COMM Corp
// Rleased to Microsoft under Contract
// Beta 1 version, 970228
// Bob Natale ([email protected])
//
// 980424 - BobN
// - Mods to SnmpStrToIpxAddress() to permit '.' char
// - as netnum/nodenum separator
// 970310 - Removed extraneous functions
//
#include "winsnmp.inc"
SNMPAPI_STATUS SNMPAPI_CALL
SnmpGetLastError (IN HSNMP_SESSION hSession)
{
DWORD nSes;
if (TaskData.hTask == 0)
return (SNMPAPI_NOT_INITIALIZED);
nSes = HandleToUlong(hSession) - 1;
if (snmpValidTableEntry(&SessDescr, nSes))
{
LPSESSION pSession = snmpGetTableEntry(&SessDescr, nSes);
return pSession->nLastError;
}
else
return (TaskData.nLastError);
} // end_SnmpGetLastError
SNMPAPI_STATUS SNMPAPI_CALL
SnmpStrToOid (IN LPCSTR string,
OUT smiLPOID dstOID)
{
smiUINT32 i;
smiUINT32 compIdx;
SNMPAPI_STATUS lError;
CHAR c;
LPSTR pSep;
// Must be initialized
if (TaskData.hTask == 0)
{
lError = SNMPAPI_NOT_INITIALIZED;
goto ERROR_OUT;
}
// use __try, __except to figure out if 'string' is a
// valid pointer. We cannot use IsBadReadPtr() here, as far as
// we have no idea for how many octets we should look.
__try
{
smiUINT32 sLen;
sLen = strlen(string);
if (sLen == 0 || sLen >= MAXOBJIDSTRSIZE)
{
lError = SNMPAPI_OID_INVALID;
goto ERROR_OUT;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
lError = SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
// see if the dstOID pointer provided by the caller points to
// a valid memory range. If null is provided, there is nothing
// the API was requested to do!
if (IsBadWritePtr (dstOID, sizeof(smiOID)))
{
lError = (dstOID == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
// Ignore initial '.' in string (UNIX-ism)
if (string[0] == '.')
string++;
// figure out how many components this OID has
// count the number of '.' in the string. The OID should
// contain this count + 1 components
dstOID->len = 0;
pSep = (LPSTR)string;
while((pSep = strchr(pSep, '.')) != NULL)
{
pSep++;
dstOID->len++;
}
dstOID->len++;
// don't allow less than 2 components
if (dstOID->len < 2)
{
lError = SNMPAPI_OID_INVALID;
goto ERROR_OUT;
}
// allocate memory for holding the numeric OID components
// this should be released by the caller, through 'SnmpFreeDescriptor()'
dstOID->ptr = (smiLPUINT32)GlobalAlloc(GPTR, dstOID->len * sizeof(smiUINT32));
if (dstOID->ptr == NULL)
{
lError = SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
compIdx = 0;
// when entering the loop, 'string' doesn't have a heading '.'
// NOTE: 123. will be accepted as 123.0
// (123.. a12.3.4 1234....5.6) are considered as invalid OIDs instead
// of truncated to (123.0 0 1234.0).
while (*string != '\0')
{
dstOID->ptr[compIdx++] = strtoul(string, &pSep, 10);
// if one of the components was overflowing, release the memory and bail out.
if (errno == ERANGE)
{
errno = 0;
lError = SNMPAPI_OID_INVALID;
GlobalFree(dstOID->ptr);
dstOID->ptr = NULL;
goto ERROR_OUT;
}
// if strtoul did not make any progress on the string (two successive dots)
// or it was blocked on something else than a separator or null-termination, then
// there was an error. The OID is invalid. API return failure
if (pSep == string ||
(*pSep != '.' && *pSep != '\0'))
{
lError = SNMPAPI_OID_INVALID; // invalid char in sequence
if (GlobalFree (dstOID->ptr)) // returns not-NULL on error
{
lError = SNMPAPI_OTHER_ERROR;
goto ERROR_OUT;
}
dstOID->ptr = NULL;
dstOID->len = 0;
goto ERROR_OUT;
}
// pSep can point only to '.' or '\0'
if (*pSep == '.')
pSep++;
// restart with string from this point
string = pSep;
}
if (dstOID->len < 2)
{
GlobalFree(dstOID->ptr);
dstOID->ptr = NULL;
lError = SNMPAPI_OID_INVALID;
goto ERROR_OUT;
}
return dstOID->len;
ERROR_OUT:
return (SaveError (0, lError));
} // end_SnmpStrToOid()
SNMPAPI_STATUS SNMPAPI_CALL
SnmpOidToStr (IN smiLPCOID srcOID,
IN smiUINT32 strLen,
OUT LPSTR strPtr)
{
SNMPAPI_STATUS lError;
smiUINT32 retLen = 0; // used for successful return
smiUINT32 oidIdx = 0; // max subids is 128
smiUINT32 tmpLen; // used for size of decoded string (with '.')
LPSTR tmpPtr = strPtr; // used for advancing strPtr
char tmpBuf[64]; // enough room for 1 32-bit decode and '.'
if (TaskData.hTask == 0)
{
lError = SNMPAPI_NOT_INITIALIZED;
goto ERROR_OUT;
}
if (!strLen)
{
lError = SNMPAPI_SIZE_INVALID;
goto ERROR_OUT;
}
if (IsBadReadPtr(srcOID, sizeof(smiOID)) ||
IsBadWritePtr(strPtr, strLen))
{
lError = (strPtr == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
if (srcOID->len == 0 || srcOID->len > 128 ||
IsBadReadPtr (srcOID->ptr, srcOID->len * sizeof(smiUINT32)))
{
lError = SNMPAPI_OID_INVALID;
goto ERROR_OUT;
}
while (oidIdx < srcOID->len)
{
_ultoa (srcOID->ptr[oidIdx++], tmpBuf, 10);
lstrcat (tmpBuf, ".");
tmpLen = lstrlen (tmpBuf);
if (strLen < (tmpLen + 1))
{
tmpBuf[strLen] = '\0';
lstrcpy (tmpPtr, tmpBuf);
lError = SNMPAPI_OUTPUT_TRUNCATED;
goto ERROR_OUT;
}
lstrcpy (tmpPtr, tmpBuf);
strLen -= tmpLen;
tmpPtr += tmpLen;
retLen += tmpLen;
} // end_while
*(--tmpPtr) = '\0';
return (retLen);
//
ERROR_OUT:
return (SaveError (0, lError));
} // end_SnmpOidToStr
SNMPAPI_STATUS SNMPAPI_CALL
SnmpOidCopy (IN smiLPCOID srcOID,
OUT smiLPOID dstOID)
{
SNMPAPI_STATUS lError;
if (TaskData.hTask == 0)
{
lError = SNMPAPI_NOT_INITIALIZED;
goto ERROR_OUT;
}
if (IsBadReadPtr (srcOID, sizeof(smiOID)) ||
IsBadReadPtr (srcOID->ptr, srcOID->len) ||
IsBadWritePtr (dstOID, sizeof(smiOID)))
{
lError = (dstOID == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
// Check input OID size
if ((srcOID->len == 0) ||(srcOID->len > MAXOBJIDSIZE))
{
lError = SNMPAPI_OID_INVALID;
goto ERROR_OUT;
}
// Using dstOID-> temporarily for byte count
dstOID->len = srcOID->len * sizeof(smiUINT32);
// App must free following alloc via SnmpFreeDescriptor()
if (!(dstOID->ptr = (smiLPUINT32)GlobalAlloc (GPTR, dstOID->len)))
{
lError = SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
CopyMemory (dstOID->ptr, srcOID->ptr, dstOID->len);
// Now make dstOID->len mean the right thing
dstOID->len = srcOID->len;
return (dstOID->len);
//
ERROR_OUT:
return (SaveError (0, lError));
} // end_SnmpOidCopy()
SNMPAPI_STATUS SNMPAPI_CALL
SnmpFreeDescriptor (IN smiUINT32 syntax,
IN smiLPOPAQUE ptr)
{
SNMPAPI_STATUS lError;
if (TaskData.hTask == 0)
{
lError = SNMPAPI_NOT_INITIALIZED;
goto ERROR_OUT;
}
if (!syntax || !ptr || !ptr->ptr)
{
lError = SNMPAPI_OPERATION_INVALID;
goto ERROR_OUT;
}
switch (syntax)
{
case SNMP_SYNTAX_OCTETS:
case SNMP_SYNTAX_IPADDR:
case SNMP_SYNTAX_OPAQUE:
case SNMP_SYNTAX_OID:
if (GlobalFree (ptr->ptr)) // returns not-NULL on error
{
lError = SNMPAPI_OTHER_ERROR;
goto ERROR_OUT;
}
ptr->ptr = NULL;
ptr->len = 0;
break;
default:
lError = SNMPAPI_SYNTAX_INVALID;
goto ERROR_OUT;
} // end_switch
return (SNMPAPI_SUCCESS);
//
ERROR_OUT:
return (SaveError (0, lError));
} // end_SnmpFreeDescriptor
// SnmpOidCompare
//
// Re-worked by 3/17/95 BobN
SNMPAPI_STATUS SNMPAPI_CALL
SnmpOidCompare (IN smiLPCOID xOID,
IN smiLPCOID yOID,
IN smiUINT32 maxlen,
OUT smiLPINT result)
{
smiUINT32 i = 0;
smiUINT32 j = 0;
SNMPAPI_STATUS lError;
if (TaskData.hTask == 0)
{
lError = SNMPAPI_NOT_INITIALIZED;
goto ERROR_OUT;
}
if (maxlen > MAXOBJIDSIZE)
{
lError = SNMPAPI_SIZE_INVALID;
goto ERROR_OUT;
}
if (IsBadReadPtr (xOID, sizeof(smiOID)) ||
IsBadReadPtr (yOID, sizeof(smiOID)))
{
lError = SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
if (IsBadReadPtr (xOID->ptr, xOID->len * sizeof(UINT)) ||
IsBadReadPtr (yOID->ptr, yOID->len * sizeof(UINT)))
{
lError = SNMPAPI_OID_INVALID;
goto ERROR_OUT;
}
// Test input pointers for readability
if (IsBadWritePtr (result, sizeof(smiINT)))
{
lError = (result == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
j = min(xOID->len, yOID->len);
if (maxlen) j = min(j, maxlen);
while (i < j)
{
if (*result = xOID->ptr[i] - yOID->ptr[i]) // deliberate assignment
return (SNMPAPI_SUCCESS); // not equal...got a winner!
i++;
}
if (j == maxlen) // asked for a limit
return (SNMPAPI_SUCCESS); // and...got a draw!
*result = xOID->len - yOID->len; // size matters!
return SNMPAPI_SUCCESS;
//
ERROR_OUT:
return (SaveError (0, lError));
} // end_SnmpOidCompare
SNMPAPI_STATUS SNMPAPI_CALL
SnmpEncodeMsg (IN HSNMP_SESSION hSession,
IN HSNMP_ENTITY hSrc,
IN HSNMP_ENTITY hDst,
IN HSNMP_CONTEXT hCtx,
IN HSNMP_PDU hPdu,
IN OUT smiLPOCTETS msgBufDesc)
{
smiUINT32 version = 0;
DWORD nCtx;
DWORD nPdu;
DWORD nVbl;
smiOCTETS tmpContext;
smiLPBYTE msgAddr = NULL;
smiUINT32 lError = SNMPAPI_SUCCESS;
HSNMP_SESSION lSession = 0;
LPPDUS pPdu;
LPENTITY pEntSrc, pEntDst;
LPCTXT pCtxt;
// Basic error checks
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
// Check for writable output buffer
if (IsBadWritePtr (msgBufDesc, sizeof(smiOCTETS)))
{
lError = (msgBufDesc == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
// srcEntity not currently used
if (hSrc)
{
if (!snmpValidTableEntry(&EntsDescr, HandleToUlong(hSrc)-1))
{
lError = SNMPAPI_ENTITY_INVALID;
goto ERROR_OUT;
}
pEntSrc = snmpGetTableEntry(&EntsDescr, HandleToUlong(hSrc)-1);
}
// dstEntity is required for *accurate* msg version info
if (hDst)
{
if (!snmpValidTableEntry(&EntsDescr, HandleToUlong(hDst)-1))
{
lError = SNMPAPI_ENTITY_INVALID;
goto ERROR_OUT;
}
pEntDst = snmpGetTableEntry(&EntsDescr, HandleToUlong(hDst)-1);
version = pEntDst->version-1;
}
nCtx = HandleToUlong(hCtx) - 1;
if (!snmpValidTableEntry(&CntxDescr, nCtx))
{
lError = SNMPAPI_CONTEXT_INVALID;
goto ERROR_OUT;
}
pCtxt = snmpGetTableEntry(&CntxDescr, nCtx);
nPdu = HandleToUlong(hPdu) - 1;
if (!snmpValidTableEntry(&PDUsDescr, nPdu))
{
ERROR_PDU:
lError = SNMPAPI_PDU_INVALID;
goto ERROR_OUT;
}
pPdu = snmpGetTableEntry(&PDUsDescr, nPdu);
// Necessary PDU data checks
nVbl = HandleToUlong(pPdu->VBL);
if (!snmpValidTableEntry(&VBLsDescr, nVbl-1))
goto ERROR_PDU;
// Check out for SNMPv1 Trap PDU type...uses different PDU structure!
// ???
// Check for SNMPv2c PDU types
if (pPdu->type == SNMP_PDU_TRAP ||
pPdu->type == SNMP_PDU_INFORM)
version = 1;
// Now Build it
tmpContext.len = pCtxt->commLen;
tmpContext.ptr = pCtxt->commStr;
if (!(BuildMessage (version, &tmpContext,
pPdu, pPdu->appReqId,
&msgAddr, &msgBufDesc->len)))
goto ERROR_PDU;
// Copy Snmp message to caller's buffer...
// App must free following alloc via SnmpFreeDescriptor()
if (!(msgBufDesc->ptr = (smiLPBYTE)GlobalAlloc (GPTR, msgBufDesc->len)))
lError = SNMPAPI_ALLOC_ERROR;
else // SUCCESS
CopyMemory (msgBufDesc->ptr, msgAddr, msgBufDesc->len);
ERROR_OUT:
// Clean up
if (msgAddr)
GlobalFree (msgAddr);
if (lError == SNMPAPI_SUCCESS)
return (msgBufDesc->len);
else // Failure cases
return (SaveError (lSession, lError));
}
SNMPAPI_STATUS SNMPAPI_CALL
SnmpDecodeMsg (IN HSNMP_SESSION hSession,
OUT LPHSNMP_ENTITY hSrc,
OUT LPHSNMP_ENTITY hDst,
OUT LPHSNMP_CONTEXT hCtx,
OUT LPHSNMP_PDU hPdu,
IN smiLPCOCTETS msgPtr)
{
DWORD nPdu;
smiLPOCTETS community;
smiUINT32 version;
SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
HSNMP_SESSION lSession = 0;
LPPDUS pPdu;
if (TaskData.hTask == 0)
{
lError = SNMPAPI_NOT_INITIALIZED;
goto ERROR_OUT;
}
if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1))
{
lError = SNMPAPI_SESSION_INVALID;
goto ERROR_OUT;
}
// Valid session...save for possible error return
lSession = hSession;
if (IsBadReadPtr(msgPtr, sizeof(smiOCTETS)) ||
IsBadReadPtr(msgPtr->ptr, msgPtr->len))
{
lError = SNMPAPI_ALLOC_ERROR;
goto ERROR_OUT;
}
if (hSrc == NULL && hDst == NULL && hCtx == NULL && hPdu == NULL)
{
lError = SNMPAPI_NOOP;
goto ERROR_OUT;
}
if ((hDst != NULL && IsBadWritePtr(hDst, sizeof(HSNMP_ENTITY))) ||
(hSrc != NULL && IsBadWritePtr(hSrc, sizeof(HSNMP_ENTITY))))
{
lError = SNMPAPI_ENTITY_INVALID;
goto ERROR_OUT;
}
if (hCtx != NULL && IsBadWritePtr(hCtx, sizeof(HSNMP_CONTEXT)))
{
lError = SNMPAPI_CONTEXT_INVALID;
goto ERROR_OUT;
}
if (IsBadWritePtr(hPdu, sizeof(HSNMP_PDU)))
{
lError = SNMPAPI_PDU_INVALID;
goto ERROR_OUT;
}
EnterCriticalSection (&cs_PDU);
lError = snmpAllocTableEntry(&PDUsDescr, &nPdu);
if (lError != SNMPAPI_SUCCESS)
goto ERROR_PRECHECK;
pPdu = snmpGetTableEntry(&PDUsDescr, nPdu);
if (ParseMessage (msgPtr->ptr, msgPtr->len, &version, &community, pPdu))
{ // non-zero = some error code
lError = SNMPAPI_MESSAGE_INVALID;
SnmpFreePdu((HSNMP_PDU) ULongToPtr(nPdu+1));
goto ERROR_PRECHECK;
}
if (hDst != NULL) *hDst = 0;
if (hSrc != NULL) *hSrc = 0;
if (hCtx != NULL)
{
smiUINT32 nMode;
EnterCriticalSection (&cs_XMODE);
SnmpGetTranslateMode (&nMode);
SnmpSetTranslateMode (SNMPAPI_UNTRANSLATED_V1);
if ((*hCtx = SnmpStrToContext (hSession, community)) == SNMPAPI_FAILURE)
{
LeaveCriticalSection (&cs_XMODE);
lError = SNMPAPI_OTHER_ERROR;
FreeOctetString (community);
SnmpFreePdu((HSNMP_PDU) ULongToPtr(nPdu+1));
goto ERROR_PRECHECK;
}
SnmpSetTranslateMode (nMode);
LeaveCriticalSection (&cs_XMODE);
}
FreeOctetString (community);
pPdu->Session = hSession;
if (hPdu != NULL)
*hPdu = (HSNMP_PDU) ULongToPtr(nPdu+1);
else
SnmpFreePdu((HSNMP_PDU) ULongToPtr(nPdu+1));
ERROR_PRECHECK:
LeaveCriticalSection (&cs_PDU);
if (lError == SNMPAPI_SUCCESS)
{
SaveError(lSession, lError);
return (msgPtr->len);
}
ERROR_OUT:
return (SaveError (lSession, lError));
} // end_SnmpDecodeMsg()
#define NETLEN 4
#define NODELEN 6
char *cHexDigits = "0123456789ABCDEF";
SNMPAPI_STATUS SNMPAPI_CALL
SnmpStrToIpxAddress (LPCSTR str, LPBYTE netnum, LPBYTE nodenum)
{
LPSTR netPtr, nodePtr, pStr;
DWORD i, j;
char tmpStr[24+1];
BYTE c1, c2;
if (!str || !netnum || !nodenum)
return (SNMPAPI_FAILURE);
strncpy (tmpStr, str,24);
tmpStr[24] = '\0';
netPtr = strtok (tmpStr, "-:.");
if (netPtr == NULL)
return (SNMPAPI_FAILURE);
if (lstrlen (netPtr) != NETLEN*2)
return (SNMPAPI_FAILURE);
nodePtr = netPtr + (NETLEN*2) + 1;
if (lstrlen (nodePtr) != NODELEN*2)
return (SNMPAPI_FAILURE);
_strupr (netPtr);
for (i = 0, j = 0; j < NETLEN; j++)
{
pStr = strchr (cHexDigits, netPtr[i++]);
if (pStr == NULL)
return (SNMPAPI_FAILURE);
c1 = (BYTE)(pStr - cHexDigits);
pStr = strchr (cHexDigits, netPtr[i++]);
if (pStr == NULL)
return (SNMPAPI_FAILURE);
c2 = (BYTE)(pStr - cHexDigits);
netnum[j] = c2 | c1 << 4;
}
_strupr (nodePtr);
for (i = 0, j = 0; j < NODELEN; j++)
{
pStr = strchr (cHexDigits, nodePtr[i++]);
if (pStr == NULL)
return (SNMPAPI_FAILURE);
c1 = (BYTE)(pStr - cHexDigits);
pStr = strchr (cHexDigits, nodePtr[i++]);
if (pStr == NULL)
return (SNMPAPI_FAILURE);
c2 = (BYTE)(pStr - cHexDigits);
nodenum[j] = c2 | c1 << 4;
}
return (SNMPAPI_SUCCESS);
}
SNMPAPI_STATUS SNMPAPI_CALL
SnmpIpxAddressToStr (LPBYTE netnum, LPBYTE nodenum, LPSTR str)
{
DWORD i, j;
for (i = 0, j = 0; i < NETLEN; i++)
{
str[j++] = cHexDigits[(netnum[i] & 0xF0) >> 4];
str[j++] = cHexDigits[netnum[i] & 0x0F];
}
str[j++] = ':';
for (i = 0; i < NODELEN; i++)
{
str[j++] = cHexDigits[(nodenum[i] & 0xF0) >> 4];
str[j++] = cHexDigits[nodenum[i] & 0x0F];
}
str[j] = '\0';
return (SNMPAPI_SUCCESS);
}