⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wsnmp_no.c

📁 windows的snmp api源码
💻 C
📖 第 1 页 / 共 3 页
字号:
// wsnmp_no.c
//
// WinSNMP Notification Functions and helpers
// Copyright 1995-1997 ACE*COMM Corp
// Rleased to Microsoft under Contract
// Beta 1 version, 970228
// Bob Natale (bnatale@acecomm.com)
//
// 970310 - Added callback session support
//        - Added v2 to v1 trap mapping
//        - Refined v1 to v2 trap mapping
//
#include "winsnmp.inc"
//
BOOL DispatchTrap (LPSAS host, smiLPOCTETS community, LPPDUS pdu);
BOOL MapV1TrapV2 (LPPDUS pdu);
smiUINT32 ParsePduHdr (smiLPBYTE msgPtr, smiUINT32 msgLen, smiLPUINT32 version, smiLPINT type, smiLPUINT32 reqID);
BOOL SetPduType (smiLPBYTE msgPtr, smiUINT32 msgLen, int pduType);
THR_TYPE WINAPI thrNotify (LPVOID);

smiUINT32 sysUpTimeValue[9]    = {1,3,6,1,2,1,1,3,0};
smiOID sysUpTimeName   = {9, sysUpTimeValue};
smiUINT32 snmpTrapOidValue[11] = {1,3,6,1,6,3,1,1,4,1,0};
smiOID snmpTrapOidName = {11, snmpTrapOidValue};
smiUINT32 snmpTrapsValue[10]   = {1,3,6,1,6,3,1,1,5,999};
smiOID snmpTrapsName   = {10, snmpTrapsValue};
smiUINT32 snmpTrapEntValue[11] = {1,3,6,1,6,3,1,1,4,3,0};
smiOID snmpTrapEntName = {11, snmpTrapEntValue};
smiUINT32 snmpTrapAddrValue[7] = {1,3,6,1,3,1057,1};
smiOID snmpTrapAddrName = {7, snmpTrapAddrValue};

void MsgNotify (smiUINT32 msgType, smiLPBYTE msgAddr, smiUINT32 msgLen, smiUINT32 nAgent, LPSAS host)
{
DWORD nFound;
DWORD nMsg;
smiUINT32 version;
smiINT pduType;
smiUINT32 reqID;
LPSESSION pSession;
LPSNMPMSG pMsg;

nMsg = ParsePduHdr (msgAddr, msgLen, &version, &pduType, &reqID);
if (nMsg != 0) // ParsePduHdr returns 0 == no_error
   {
   if (msgAddr)
   GlobalFree (msgAddr);
   return;
   }
switch (msgType)
   {
   case NP_TRAP:
   if (TrapDescr.Used && // Discard traps if no registrations
         (pduType == SNMP_PDU_INFORM ||
          pduType == SNMP_PDU_TRAP ||
          pduType == SNMP_PDU_V1TRAP))
      {
      smiLPOCTETS community;
      LPPDUS pdu;
      BOOL bConvert;
      pdu = GlobalAlloc (GPTR, sizeof(PDUS));
      if (pdu == NULL)
         goto DONE_TRAP;
      nMsg = ParseMessage (msgAddr, msgLen, &version, &community, pdu);
      if (nMsg != 0) // ParseMessage returns 0 == no_error
         goto DONE_PDU;
      if (pduType == SNMP_PDU_INFORM)
         { // Send the Inform acknowledgment response
         SOCKET s;
         SetPduType (msgAddr, msgLen, SNMP_PDU_RESPONSE);
         if (host->ipx.sa_family == AF_IPX)
            s = TaskData.ipxSock;
         else
            s = TaskData.ipSock;
         sendto (s, msgAddr, msgLen, 0, (LPSOCKADDR)host, sizeof(SOCKADDR));
         SetPduType (msgAddr, msgLen, SNMP_PDU_INFORM);
         }
      bConvert = TRUE;
      if (pduType == SNMP_PDU_V1TRAP)           // If v1 trap...
         bConvert = MapV1TrapV2 (pdu);          // convert to v2 trap
      if (bConvert)
         DispatchTrap (host, community, pdu);   // always v2 here
      // Cleanup is the same regardless of success or failure
      FreeVarBindList (pdu->VBL_addr);  // Checks for NULL
      FreeV1Trap (pdu->v1Trap);         // ditto
      FreeOctetString (community);      // ditto
      DONE_PDU:
      GlobalFree (pdu);
      } // end_if Trap_or_Inform PDU
   DONE_TRAP:
   GlobalFree (msgAddr);
   return; // end_case NP_TRAP

   case NP_RESPONSE:
   if (pduType != SNMP_PDU_RESPONSE)
      {
      GlobalFree (msgAddr);
      return;
      }
   EnterCriticalSection (&cs_MSG);

   for (nFound=0, nMsg=0; nFound<MsgDescr.Used && nMsg<MsgDescr.Allocated; nMsg++)
      {
      pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
      if (!pMsg->Session)
         continue;
	  nFound++;
      if ((pMsg->Status == NP_SENT) && // Must have been sent!
          (pMsg->dllReqId == reqID))   // Must match up!
         {
         pMsg->Status = NP_RCVD;       // ResponsePDU!
         // Release sent packet message
         if (pMsg->Addr)
            GlobalFree (pMsg->Addr);
         // Point to received packet message
         pMsg->Addr = msgAddr;
         pMsg->Size = msgLen;
         LeaveCriticalSection (&cs_MSG);
		 pSession = snmpGetTableEntry(&SessDescr, HandleToUlong(pMsg->Session) - 1);
         if (pSession->fCallBack)
            { // callback session notification mode
            EnterCriticalSection (&cs_SESSION);
            if (pSession->thrHandle)
               {
               if (pSession->thrCount != 0xFFFFFFFF)
                  pSession->thrCount++;
               SetEvent (pSession->thrEvent);
               }
            else
               FreeMsg (nMsg);
            LeaveCriticalSection (&cs_SESSION);
            }
         else
            { // window/message session notification mode
            if (IsWindow(pSession->hWnd))
               {
               pMsg->Status = NP_READY;
               PostMessage (pSession->hWnd,
                            pSession->wMsg,
                            0, pMsg->appReqId);
               }
            else
               FreeMsg (nMsg);
            }
         return;  // Matched response with request
         } // end_if
      } // end_for
   // If we fall through the for loop without finding a match,
   //  this must be a spurious message from agent...discard
   GlobalFree (msgAddr);
   LeaveCriticalSection (&cs_MSG);
   return; // end_case NP_RESPONSE

   case NP_REQUEST:
   // To allow for AgentX Master Agents and Mid-Level-Managers
   // any type of PDU may be accepted on this channel - BobN 4/8/97
   // Get a msg slot
   EnterCriticalSection (&cs_MSG);
   if (snmpAllocTableEntry(&MsgDescr, &nMsg) != SNMPAPI_SUCCESS)
   {
       LeaveCriticalSection(&cs_MSG);
       return;
   }
   pMsg = snmpGetTableEntry(&MsgDescr, nMsg);

   pMsg->Session = ((LPAGENT)snmpGetTableEntry(&AgentDescr, nAgent))->Session;
   pMsg->Status = NP_RCVD;       // In-bound request
   pMsg->Type = pduType;
   pMsg->Addr = msgAddr;
   pMsg->Size = msgLen;
   pMsg->appReqId = pMsg->dllReqId = reqID;
   CopyMemory (&(pMsg->Host), host, sizeof(SAS));
   LeaveCriticalSection (&cs_MSG);
   pSession = snmpGetTableEntry(&SessDescr, HandleToUlong(pMsg->Session) - 1);
   if (pSession->fCallBack)
      { // callback session notification mode
     EnterCriticalSection (&cs_SESSION);
      if (pSession->thrHandle)
         {
         if (pSession->thrCount != 0xFFFFFFFF)
            pSession->thrCount++;
         SetEvent (pSession->thrEvent);
         }
      else
         {
         FreeMsg (nMsg);
         }
      LeaveCriticalSection (&cs_SESSION);
      }
   else
      {
      if (IsWindow(pSession->hWnd))
         {
         pMsg->Status = NP_READY;
         PostMessage (pSession->hWnd,
                      pSession->wMsg,
                      0, pMsg->appReqId);
         }
      else
         FreeMsg (nMsg);
      }
   break;

   default:
   GlobalFree (msgAddr);
   break;
   } // end_switch msgType
return;
} // end_MsgNotify

THR_TYPE WINAPI thrNotify (LPVOID cbSessionSlot)
{
    DWORD           nSes = (DWORD)((DWORD_PTR)cbSessionSlot);
    HSNMP_SESSION   hSession = (HSNMP_SESSION)(nSes + 1);
    DWORD           nUsed, nMsg;
    WPARAM          wParam;
    LPARAM          lParam;
    BOOL            bFound, bWillBlock;
	LPSESSION		pSession;
    LPSNMPMSG       pMsg;

    // pSession->thrCount counts the number of requests. External threads increment it
    // each time they know something has changed in the message table (message expired or received)
    // thrNotify decrements it each time it scans the message table.
    do
    {
        EnterCriticalSection (&cs_SESSION);
		pSession = snmpGetTableEntry(&SessDescr, nSes);
        if (pSession->thrCount != 0xFFFFFFFF &&
            pSession->thrCount != 0)
            pSession->thrCount-- ;
        bWillBlock = pSession->thrCount == 0;
        LeaveCriticalSection (&cs_SESSION);

        // The thread will block only if the pSession->thrCount was 0 (tested in critical
        // section). It will be unblocked by external threads, from inside the same critical section.
        if (bWillBlock)
            WaitForSingleObject (pSession->thrEvent, INFINITE);

        // termination is requested, just break the loop
        if (pSession->thrCount == 0xFFFFFFFF)
            break;

        bFound = FALSE;
        // Find a waiting Msg for this session to process
        EnterCriticalSection (&cs_MSG);
        for (nUsed=0, nMsg=0;
             nUsed<MsgDescr.Used && nMsg<MsgDescr.Allocated;
             nMsg++)
        {
            pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
            if (pMsg->Session == hSession &&
                (pMsg->Status == NP_RCVD || pMsg->Status == NP_EXPIRED))
            {
                // the message was found. It might be already received, or it might
                // be timed out. Either case, the notification function has to be called.
                wParam = pMsg->Status == NP_RCVD ? 0 : SNMPAPI_TL_TIMEOUT ;
                lParam = pMsg->appReqId;

                if (wParam == SNMPAPI_TL_TIMEOUT)
                    FreeMsg(nMsg); // no more need for this expired bugger
                else
                    pMsg->Status = NP_READY; // mark it for SnmpRecvMsg()

                bFound = TRUE;
                // as the message was found, no reason to loop further
                break;
            }

            // update nFound to avoid searching more than the messages available
            nUsed += (pMsg->Session != 0);
        }
        LeaveCriticalSection (&cs_MSG);

        if (bFound)
        {
            //if a message was found for this session, call the notification function
            (*(pSession->fCallBack)) (hSession,
                                      pSession->hWnd,
                                      pSession->wMsg,
                                      wParam,
                                      lParam,
                                      pSession->lpClientData);
        }

    } while (TRUE);

    _endthreadex(0);

    return (0);
} // end_thrNotify

THR_TYPE WINAPI thrManager (LPVOID xSock)
{
DWORD  iBytes;
int    nSock;
fd_set readFDS;
SOCKET *pSock = (SOCKET*)xSock;
SOCKET tSock = *pSock;
SAS    host;
smiLPBYTE rMsgPtr;
int    fLen;
while (TRUE)
   {
   FD_ZERO (&readFDS);
   // Note:  strategy used in this block to assign a value
   // to "fLen" is important for Solaris and benign for Win32
   FD_SET (tSock, &readFDS);
   fLen = (int)tSock;
   fLen++;
   // Must preserve value of fLen across loops
   nSock = select (fLen, &readFDS, NULL, NULL, NULL);
   if (nSock == SOCKET_ERROR || *pSock == INVALID_SOCKET)
      goto DONE;
   // Only one socket monitored per thread, hence
   // FD_ISSET can be safely assumed at this point
   nSock = ioctlsocket (tSock, FIONREAD, &iBytes);
   if (nSock == SOCKET_ERROR || *pSock == INVALID_SOCKET)
      goto DONE;
   // Find the message buffer address...
   rMsgPtr = GlobalAlloc (GPTR, iBytes);
   if (rMsgPtr == NULL)
      { // No space error...throw away the message...
      recvfrom (tSock, (LPSTR)&nSock, 1, 0, NULL, NULL);
      if (*pSock == INVALID_SOCKET)
          goto DONE;
      // ...and call it quits.
      continue;
      }
   nSock = sizeof(SAS);
   // get the datagram and the address of the host that sent it
   iBytes = recvfrom (tSock, rMsgPtr, iBytes, 0, (LPSOCKADDR)&host, &nSock);
   if (iBytes != SOCKET_ERROR && *pSock != INVALID_SOCKET)
      MsgNotify (NP_RESPONSE, rMsgPtr, iBytes, 0, &host);
   } // end_while
DONE:
return (0);
} // end_thrManager

THR_TYPE WINAPI thrTimer (LPVOID nTask)
{ // Clean-up any timed-out messages
BOOL bFree;
DWORD lTicks, nMsg;
DWORD nFound;
SOCKET tSock;
LPSNMPMSG pMsg;

// This thread won't be needed immediately upon creation.
// It sleeps/suspends itself as appropriate.
// SnmpSendMsg() resumes it for each message sent
// SnmpCleanup() resumes it to signal termination.
while (TRUE)
   {// Once per second granularity
#ifdef SOLARIS
   sleep (1);
#else
   Sleep (1000);
#endif // SOLARIS
   // Check for termination request
   if (TaskData.timerThread == NULL)
      goto DONE;
   // If no msgs, go back to sleep
   if (MsgDescr.Used == 0)
      continue;
   EnterCriticalSection (&cs_MSG);
   for (nMsg=0, nFound=0; nFound<MsgDescr.Used && nMsg<MsgDescr.Allocated; nMsg++)
      {
      pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
      if (!pMsg->Session)           // Skip unused slots
         continue;
      nFound++; // Signal break when last used slot is processed
      if (pMsg->Status != NP_SENT)  // Skip pending and
         continue;                           // received messages
      lTicks = GetTickCount();               // update current time
      // Following test revised on 10/18/96 by BobN
      // Message "tick-time" rather than "TTL" now stored in MSG
      // to enable test for Windows timer wrap (49.7 days)
      if (pMsg->Wait + pMsg->Ticks > lTicks  &&  // MSG TTL test
          pMsg->Ticks <= lTicks)                 // Timer wrap test
         continue;                            // Retain the message
      bFree = TRUE; // Prepare to free the message slot
      if (pMsg->nRetransmitMode)
         {
         if (pMsg->Tries)
            {
            //WriteSocket (nMsg);
            // Determine which socket to use
            if (pMsg->Host.ipx.sa_family == AF_IPX)
               tSock = TaskData.ipxSock;
            else
               tSock = TaskData.ipSock;
            // Send the data
            sendto (tSock, pMsg->Addr, pMsg->Size,
                    0, (LPSOCKADDR)&(pMsg->Host), sizeof(SAS));
            // Need to check for SOCKET_ERROR!
            // end_WriteSocket
            pMsg->Ticks = lTicks;
            pMsg->Tries--;    // Record the attempt
            if (!pMsg->Tries) // No further retries?
               {                       // Release buffer space
               GlobalFree (pMsg->Addr);
               pMsg->Addr = NULL;
               pMsg->Size = 0;
               }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -