// wsnmp_pd.c // // WinSNMP PDU Functions and helpers // Copyright 1995-1997 ACE*COMM Corp // Rleased to Microsoft under Contract // Beta 1 version, 970228 // Bob Natale (bnatale@acecomm.com) // // Removed extraneous functions // #include "winsnmp.inc" LPVARBIND SnmpCopyVbl (LPVARBIND); // PDU Functions // SnmpCreatePdu HSNMP_PDU SNMPAPI_CALL SnmpCreatePdu (IN HSNMP_SESSION hSession, IN smiINT PDU_type, IN smiINT32 request_id, IN smiINT error_status, IN smiINT error_index, IN HSNMP_VBL hVbl) { DWORD nPdu; 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; } // We have a valid session at this point... lSession = hSession; // save it for possible error return if (hVbl) { if (!snmpValidTableEntry(&VBLsDescr, HandleToUlong(hVbl)-1)) { lError = SNMPAPI_VBL_INVALID; goto ERROR_OUT; } } if (!PDU_type) // NULL is allowed and defaults to SNMP_PDU_GETNEXT PDU_type = SNMP_PDU_GETNEXT; switch (PDU_type) { case SNMP_PDU_GET: case SNMP_PDU_GETNEXT: case SNMP_PDU_RESPONSE: case SNMP_PDU_SET: case SNMP_PDU_INFORM: case SNMP_PDU_TRAP: case SNMP_PDU_GETBULK: break; case SNMP_PDU_V1TRAP: default: 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); // Initialize new PDU components pPdu->Session = hSession; pPdu->type = PDU_type; pPdu->errStatus = error_status; pPdu->errIndex = error_index; // If RequestID=0 at this point, assign one (which may be 0) pPdu->appReqId = (request_id) ? request_id : ++(TaskData.nLastReqId); pPdu->VBL_addr = NULL; pPdu->VBL = (hVbl) ? hVbl : 0; ERROR_PRECHECK: LeaveCriticalSection (&cs_PDU); if (lError == SNMPAPI_SUCCESS) return ((HSNMP_PDU) ULongToPtr(nPdu+1)); else ERROR_OUT: return ((HSNMP_PDU) ULongToPtr(SaveError(lSession, lError))); } // end_SnmpCreatePdu // SnmpGetPduData SNMPAPI_STATUS SNMPAPI_CALL SnmpGetPduData (IN HSNMP_PDU hPdu, OUT smiLPINT PDU_type, OUT smiLPINT32 request_id, OUT smiLPINT error_status, OUT smiLPINT error_index, OUT LPHSNMP_VBL hVbl) { DWORD nPdu = HandleToUlong(hPdu) - 1; DWORD done = 0; HSNMP_SESSION hSession; SNMPAPI_STATUS lError = SNMPAPI_SUCCESS; HSNMP_SESSION lSession = 0; LPPDUS pPdu; LPVBLS pVbl; if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&PDUsDescr, nPdu)) { lError = SNMPAPI_PDU_INVALID; goto ERROR_OUT; } pPdu = snmpGetTableEntry(&PDUsDescr, nPdu); // Use PDU's session for (possibly) creating hVbl later hSession = pPdu->Session; if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1)) { lError = SNMPAPI_SESSION_INVALID; goto ERROR_OUT; } lSession = hSession; // Save for possible error return if (PDU_type) { *PDU_type = pPdu->type; done++; } if (request_id) { *request_id = pPdu->appReqId; done++; } if (error_status) { *error_status = pPdu->errStatus; done++; } if (error_index) { *error_index = pPdu->errIndex; done++; } if (hVbl) { DWORD nVbl; // Important control variable *hVbl = 0; EnterCriticalSection (&cs_VBL); // First case is on a created (not received) PDU // which has not yet been assigned a VBL if ((!pPdu->VBL) && (!pPdu->VBL_addr)) goto DONE_VBL; // If there is a VBL already assinged to the PDU, // then duplicate it if (pPdu->VBL) { // Per policy, create a new hVbl resource for the calling app if (!(*hVbl = SnmpDuplicateVbl (hSession, pPdu->VBL))) { lError = SNMPAPI_VBL_INVALID; goto ERROR_PRECHECK; } goto DONE_VBL; } // This must be a received PDU and // the first call to extract the VBL lError = snmpAllocTableEntry(&VBLsDescr, &nVbl); if (lError != SNMPAPI_SUCCESS) goto ERROR_PRECHECK; pVbl = snmpGetTableEntry(&VBLsDescr, nVbl); pVbl->Session = hSession; pVbl->vbList = pPdu->VBL_addr; // Clear received vbList address...IMPORTANT! pPdu->VBL_addr = NULL; *hVbl = pPdu->VBL = (HSNMP_VBL) ULongToPtr(nVbl+1); DONE_VBL: done++; ERROR_PRECHECK: LeaveCriticalSection (&cs_VBL); } // end_if vbl if (done == 0) lError = SNMPAPI_NOOP; if (lError == SNMPAPI_SUCCESS) return (SNMPAPI_SUCCESS); ERROR_OUT: return (SaveError (lSession, lError)); } // end_SnmpGetPduData // SnmpSetPduData SNMPAPI_STATUS SNMPAPI_CALL SnmpSetPduData (IN HSNMP_PDU hPdu, IN const smiINT FAR *PDU_type, IN const smiINT32 FAR *request_id, IN const smiINT FAR *non_repeaters, IN const smiINT FAR *max_repetitions, IN const HSNMP_VBL FAR *hVbl) { DWORD nPdu = HandleToUlong(hPdu) - 1; DWORD done = 0; SNMPAPI_STATUS lError = SNMPAPI_SUCCESS; HSNMP_SESSION lSession = 0; LPPDUS pPdu; if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&PDUsDescr, nPdu)) { lError = SNMPAPI_PDU_INVALID; goto ERROR_OUT; } pPdu = snmpGetTableEntry(&PDUsDescr, nPdu); lSession = pPdu->Session; // Save for possible error return EnterCriticalSection (&cs_PDU); if (!IsBadReadPtr((LPVOID)PDU_type, sizeof(smiINT))) { if (*PDU_type == SNMP_PDU_V1TRAP) { lError = SNMPAPI_PDU_INVALID; goto ERROR_OUT; } pPdu->type = *PDU_type; done++; } if (!IsBadReadPtr((LPVOID)request_id, sizeof(smiINT32))) { pPdu->appReqId = *request_id; done++; } if (!IsBadReadPtr((LPVOID)non_repeaters, sizeof(smiINT))) { pPdu->errStatus = *non_repeaters; done++; } if (!IsBadReadPtr((LPVOID)max_repetitions, sizeof(smiINT))) { pPdu->errIndex = *max_repetitions; done++; } if (!IsBadReadPtr((LPVOID)hVbl, sizeof(HSNMP_VBL))) { // Assign new vbl HSNMP_VBL tVbl = *hVbl; // Check for validity if (!snmpValidTableEntry(&VBLsDescr, HandleToUlong(tVbl)-1)) { // If not, disallow operation lError = SNMPAPI_VBL_INVALID; goto ERROR_PRECHECK; } pPdu->VBL = tVbl; // Following case can happen if a a vbl is assigned to a // response pdu which never had its vbl dereferenced... if (pPdu->VBL_addr) //...then is must be freed FreeVarBindList (pPdu->VBL_addr); pPdu->VBL_addr = NULL; done++; } // end_if vbl ERROR_PRECHECK: LeaveCriticalSection (&cs_PDU); if (done == 0) lError = ((PDU_type == NULL) && (request_id == NULL) && (non_repeaters == NULL) && (max_repetitions == NULL) && (hVbl == NULL)) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR; if (lError == SNMPAPI_SUCCESS) return (SNMPAPI_SUCCESS); ERROR_OUT: return (SaveError (lSession, lError)); } // end_SnmpSetPduData // SnmpDuplicatePdu HSNMP_PDU SNMPAPI_CALL SnmpDuplicatePdu (IN HSNMP_SESSION hSession, IN HSNMP_PDU hPdu) { DWORD lPdu = HandleToUlong(hPdu) - 1; DWORD nPdu; SNMPAPI_STATUS lError = SNMPAPI_SUCCESS; HSNMP_SESSION lSession = 0; LPPDUS pOldPdu, pNewPdu; 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 for possible error return if (!snmpValidTableEntry(&PDUsDescr, lPdu) || (pOldPdu = snmpGetTableEntry(&PDUsDescr, lPdu))->type == SNMP_PDU_V1TRAP) { lError = SNMPAPI_PDU_INVALID; goto ERROR_OUT; } EnterCriticalSection (&cs_PDU); lError = snmpAllocTableEntry(&PDUsDescr, &nPdu); if (lError != SNMPAPI_SUCCESS) goto ERROR_PRECHECK; pNewPdu = snmpGetTableEntry(&PDUsDescr, nPdu); CopyMemory (pNewPdu, pOldPdu, sizeof(PDUS)); pNewPdu->Session = hSession; // Can be different // Setting the VBL value in the duplicated PDU is "tricky"... // If there is a VBL value, just replicate it and that's that. // If VBL = 0 and there is no VBL_addr attached to the pdu_ptr, // then the VBL value is 0 and is already set from the original PDU. // Otherwise, this is a received PDU from which the varbindlist has // not yet been extracted and must, therefore, be re-produced. // This third case is covered in the next *2* lines. if ((!pOldPdu->VBL) && pOldPdu->VBL_addr) { if (!(pNewPdu->VBL_addr = SnmpCopyVbl (pOldPdu->VBL_addr))) { lError = SNMPAPI_ALLOC_ERROR; } } ERROR_PRECHECK: LeaveCriticalSection (&cs_PDU); if (lError == SNMPAPI_SUCCESS) return ((HSNMP_PDU) ULongToPtr(nPdu+1)); ERROR_OUT: return ((HSNMP_PDU) ULongToPtr(SaveError(lSession, lError))); } // end_SnmpDuplicatePdu // SnmpFreePdu SNMPAPI_STATUS SNMPAPI_CALL SnmpFreePdu (IN HSNMP_PDU hPdu) { DWORD nPdu = HandleToUlong(hPdu) - 1; SNMPAPI_STATUS lError = SNMPAPI_SUCCESS; LPPDUS pPdu; if (TaskData.hTask == 0) { lError = SNMPAPI_NOT_INITIALIZED; goto ERROR_OUT; } if (!snmpValidTableEntry(&PDUsDescr, nPdu)) { lError = SNMPAPI_PDU_INVALID; goto ERROR_OUT; } pPdu = snmpGetTableEntry(&PDUsDescr, nPdu); EnterCriticalSection (&cs_PDU); if (pPdu->VBL_addr) FreeVarBindList (pPdu->VBL_addr); if (pPdu->v1Trap) FreeV1Trap (pPdu->v1Trap); snmpFreeTableEntry(&PDUsDescr, nPdu); LeaveCriticalSection (&cs_PDU); return (SNMPAPI_SUCCESS); ERROR_OUT: return (SaveError (0, lError)); } // end_SnmpfreePdu