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.

1198 lines
42 KiB

  1. // wsnmp_no.c
  2. //
  3. // WinSNMP Notification Functions and helpers
  4. // Copyright 1995-1997 ACE*COMM Corp
  5. // Rleased to Microsoft under Contract
  6. // Beta 1 version, 970228
  7. // Bob Natale ([email protected])
  8. //
  9. // 970310 - Added callback session support
  10. // - Added v2 to v1 trap mapping
  11. // - Refined v1 to v2 trap mapping
  12. //
  13. #include "winsnmp.inc"
  14. //
  15. BOOL DispatchTrap (LPSAS host, smiLPOCTETS community, LPPDUS pdu);
  16. BOOL MapV1TrapV2 (LPPDUS pdu);
  17. smiUINT32 ParsePduHdr (smiLPBYTE msgPtr, smiUINT32 msgLen, smiLPUINT32 version, smiLPINT type, smiLPUINT32 reqID);
  18. BOOL SetPduType (smiLPBYTE msgPtr, smiUINT32 msgLen, int pduType);
  19. THR_TYPE WINAPI thrNotify (LPVOID);
  20. smiUINT32 sysUpTimeValue[9] = {1,3,6,1,2,1,1,3,0};
  21. smiOID sysUpTimeName = {9, sysUpTimeValue};
  22. smiUINT32 snmpTrapOidValue[11] = {1,3,6,1,6,3,1,1,4,1,0};
  23. smiOID snmpTrapOidName = {11, snmpTrapOidValue};
  24. smiUINT32 snmpTrapsValue[10] = {1,3,6,1,6,3,1,1,5,999};
  25. smiOID snmpTrapsName = {10, snmpTrapsValue};
  26. smiUINT32 snmpTrapEntValue[11] = {1,3,6,1,6,3,1,1,4,3,0};
  27. smiOID snmpTrapEntName = {11, snmpTrapEntValue};
  28. smiUINT32 snmpTrapAddrValue[7] = {1,3,6,1,3,1057,1};
  29. smiOID snmpTrapAddrName = {7, snmpTrapAddrValue};
  30. void MsgNotify (smiUINT32 msgType, smiLPBYTE msgAddr, smiUINT32 msgLen, smiUINT32 nAgent, LPSAS host)
  31. {
  32. DWORD nFound;
  33. DWORD nMsg;
  34. smiUINT32 version;
  35. smiINT pduType;
  36. smiUINT32 reqID;
  37. LPSESSION pSession;
  38. LPSNMPMSG pMsg;
  39. nMsg = ParsePduHdr (msgAddr, msgLen, &version, &pduType, &reqID);
  40. if (nMsg != 0) // ParsePduHdr returns 0 == no_error
  41. {
  42. if (msgAddr)
  43. GlobalFree (msgAddr);
  44. return;
  45. }
  46. switch (msgType)
  47. {
  48. case NP_TRAP:
  49. if (TrapDescr.Used && // Discard traps if no registrations
  50. (pduType == SNMP_PDU_INFORM ||
  51. pduType == SNMP_PDU_TRAP ||
  52. pduType == SNMP_PDU_V1TRAP))
  53. {
  54. smiLPOCTETS community;
  55. LPPDUS pdu;
  56. BOOL bConvert;
  57. pdu = GlobalAlloc (GPTR, sizeof(PDUS));
  58. if (pdu == NULL)
  59. goto DONE_TRAP;
  60. nMsg = ParseMessage (msgAddr, msgLen, &version, &community, pdu);
  61. if (nMsg != 0) // ParseMessage returns 0 == no_error
  62. goto DONE_PDU;
  63. if (pduType == SNMP_PDU_INFORM)
  64. { // Send the Inform acknowledgment response
  65. SOCKET s;
  66. SetPduType (msgAddr, msgLen, SNMP_PDU_RESPONSE);
  67. if (host->ipx.sa_family == AF_IPX)
  68. s = TaskData.ipxSock;
  69. else
  70. s = TaskData.ipSock;
  71. sendto (s, msgAddr, msgLen, 0, (LPSOCKADDR)host, sizeof(SOCKADDR));
  72. SetPduType (msgAddr, msgLen, SNMP_PDU_INFORM);
  73. }
  74. bConvert = TRUE;
  75. if (pduType == SNMP_PDU_V1TRAP) // If v1 trap...
  76. bConvert = MapV1TrapV2 (pdu); // convert to v2 trap
  77. if (bConvert)
  78. DispatchTrap (host, community, pdu); // always v2 here
  79. // Cleanup is the same regardless of success or failure
  80. FreeVarBindList (pdu->VBL_addr); // Checks for NULL
  81. FreeV1Trap (pdu->v1Trap); // ditto
  82. FreeOctetString (community); // ditto
  83. DONE_PDU:
  84. GlobalFree (pdu);
  85. } // end_if Trap_or_Inform PDU
  86. DONE_TRAP:
  87. GlobalFree (msgAddr);
  88. return; // end_case NP_TRAP
  89. case NP_RESPONSE:
  90. if (pduType != SNMP_PDU_RESPONSE)
  91. {
  92. GlobalFree (msgAddr);
  93. return;
  94. }
  95. EnterCriticalSection (&cs_MSG);
  96. for (nFound=0, nMsg=0; nFound<MsgDescr.Used && nMsg<MsgDescr.Allocated; nMsg++)
  97. {
  98. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  99. if (!pMsg->Session)
  100. continue;
  101. nFound++;
  102. if ((pMsg->Status == NP_SENT) && // Must have been sent!
  103. (pMsg->dllReqId == reqID)) // Must match up!
  104. {
  105. pMsg->Status = NP_RCVD; // ResponsePDU!
  106. // Release sent packet message
  107. if (pMsg->Addr)
  108. GlobalFree (pMsg->Addr);
  109. // Point to received packet message
  110. pMsg->Addr = msgAddr;
  111. pMsg->Size = msgLen;
  112. LeaveCriticalSection (&cs_MSG);
  113. pSession = snmpGetTableEntry(&SessDescr, HandleToUlong(pMsg->Session) - 1);
  114. if (pSession->fCallBack)
  115. { // callback session notification mode
  116. EnterCriticalSection (&cs_SESSION);
  117. if (pSession->thrHandle)
  118. {
  119. if (pSession->thrCount != 0xFFFFFFFF)
  120. pSession->thrCount++;
  121. SetEvent (pSession->thrEvent);
  122. }
  123. else
  124. FreeMsg (nMsg);
  125. LeaveCriticalSection (&cs_SESSION);
  126. }
  127. else
  128. { // window/message session notification mode
  129. if (IsWindow(pSession->hWnd))
  130. {
  131. pMsg->Status = NP_READY;
  132. PostMessage (pSession->hWnd,
  133. pSession->wMsg,
  134. 0, pMsg->appReqId);
  135. }
  136. else
  137. FreeMsg (nMsg);
  138. }
  139. return; // Matched response with request
  140. } // end_if
  141. } // end_for
  142. // If we fall through the for loop without finding a match,
  143. // this must be a spurious message from agent...discard
  144. GlobalFree (msgAddr);
  145. LeaveCriticalSection (&cs_MSG);
  146. return; // end_case NP_RESPONSE
  147. case NP_REQUEST:
  148. // To allow for AgentX Master Agents and Mid-Level-Managers
  149. // any type of PDU may be accepted on this channel - BobN 4/8/97
  150. // Get a msg slot
  151. EnterCriticalSection (&cs_MSG);
  152. if (snmpAllocTableEntry(&MsgDescr, &nMsg) != SNMPAPI_SUCCESS)
  153. {
  154. LeaveCriticalSection(&cs_MSG);
  155. GlobalFree (msgAddr);
  156. return;
  157. }
  158. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  159. pMsg->Session = ((LPAGENT)snmpGetTableEntry(&AgentDescr, nAgent))->Session;
  160. pMsg->Status = NP_RCVD; // In-bound request
  161. pMsg->Type = pduType;
  162. pMsg->Addr = msgAddr;
  163. pMsg->Size = msgLen;
  164. pMsg->appReqId = pMsg->dllReqId = reqID;
  165. CopyMemory (&(pMsg->Host), host, sizeof(SAS));
  166. LeaveCriticalSection (&cs_MSG);
  167. pSession = snmpGetTableEntry(&SessDescr, HandleToUlong(pMsg->Session) - 1);
  168. if (pSession->fCallBack)
  169. { // callback session notification mode
  170. EnterCriticalSection (&cs_SESSION);
  171. if (pSession->thrHandle)
  172. {
  173. if (pSession->thrCount != 0xFFFFFFFF)
  174. pSession->thrCount++;
  175. SetEvent (pSession->thrEvent);
  176. }
  177. else
  178. {
  179. FreeMsg (nMsg);
  180. }
  181. LeaveCriticalSection (&cs_SESSION);
  182. }
  183. else
  184. {
  185. if (IsWindow(pSession->hWnd))
  186. {
  187. pMsg->Status = NP_READY;
  188. PostMessage (pSession->hWnd,
  189. pSession->wMsg,
  190. 0, pMsg->appReqId);
  191. }
  192. else
  193. FreeMsg (nMsg);
  194. }
  195. break;
  196. default:
  197. GlobalFree (msgAddr);
  198. break;
  199. } // end_switch msgType
  200. return;
  201. } // end_MsgNotify
  202. THR_TYPE WINAPI thrNotify (LPVOID cbSessionSlot)
  203. {
  204. DWORD nSes = (DWORD)((DWORD_PTR)cbSessionSlot);
  205. HSNMP_SESSION hSession = (HSNMP_SESSION) ULongToPtr(nSes + 1);
  206. DWORD nUsed, nMsg;
  207. WPARAM wParam;
  208. LPARAM lParam;
  209. BOOL bFound, bWillBlock;
  210. LPSESSION pSession;
  211. LPSNMPMSG pMsg;
  212. // pSession->thrCount counts the number of requests. External threads increment it
  213. // each time they know something has changed in the message table (message expired or received)
  214. // thrNotify decrements it each time it scans the message table.
  215. do
  216. {
  217. EnterCriticalSection (&cs_SESSION);
  218. pSession = snmpGetTableEntry(&SessDescr, nSes);
  219. if (pSession->thrCount != 0xFFFFFFFF &&
  220. pSession->thrCount != 0)
  221. pSession->thrCount-- ;
  222. bWillBlock = pSession->thrCount == 0;
  223. LeaveCriticalSection (&cs_SESSION);
  224. // The thread will block only if the pSession->thrCount was 0 (tested in critical
  225. // section). It will be unblocked by external threads, from inside the same critical section.
  226. if (bWillBlock)
  227. WaitForSingleObject (pSession->thrEvent, INFINITE);
  228. // termination is requested, just break the loop
  229. if (pSession->thrCount == 0xFFFFFFFF)
  230. break;
  231. bFound = FALSE;
  232. // Find a waiting Msg for this session to process
  233. EnterCriticalSection (&cs_MSG);
  234. for (nUsed=0, nMsg=0;
  235. nUsed<MsgDescr.Used && nMsg<MsgDescr.Allocated;
  236. nMsg++)
  237. {
  238. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  239. if (pMsg->Session == hSession &&
  240. (pMsg->Status == NP_RCVD || pMsg->Status == NP_EXPIRED))
  241. {
  242. // the message was found. It might be already received, or it might
  243. // be timed out. Either case, the notification function has to be called.
  244. wParam = pMsg->Status == NP_RCVD ? 0 : SNMPAPI_TL_TIMEOUT ;
  245. lParam = pMsg->appReqId;
  246. if (wParam == SNMPAPI_TL_TIMEOUT)
  247. FreeMsg(nMsg); // no more need for this expired bugger
  248. else
  249. pMsg->Status = NP_READY; // mark it for SnmpRecvMsg()
  250. bFound = TRUE;
  251. // as the message was found, no reason to loop further
  252. break;
  253. }
  254. // update nFound to avoid searching more than the messages available
  255. nUsed += (pMsg->Session != 0);
  256. }
  257. LeaveCriticalSection (&cs_MSG);
  258. if (bFound)
  259. {
  260. //if a message was found for this session, call the notification function
  261. (*(pSession->fCallBack)) (hSession,
  262. pSession->hWnd,
  263. pSession->wMsg,
  264. wParam,
  265. lParam,
  266. pSession->lpClientData);
  267. }
  268. } while (TRUE);
  269. _endthreadex(0);
  270. return (0);
  271. } // end_thrNotify
  272. THR_TYPE WINAPI thrManager (LPVOID xSock)
  273. {
  274. DWORD iBytes;
  275. int nSock;
  276. fd_set readFDS;
  277. SOCKET *pSock = (SOCKET*)xSock;
  278. SOCKET tSock = *pSock;
  279. SAS host;
  280. smiLPBYTE rMsgPtr;
  281. int fLen;
  282. struct timeval tvTimeout; // timeout for select
  283. // select with timeout so that we can response to hExitEvent in signaled state
  284. tvTimeout.tv_sec = 1; // 1 sec. timeout value
  285. tvTimeout.tv_usec = 0; // When select returns, the contents of the
  286. // tvTimeout structure are not altered.
  287. while (TRUE)
  288. {
  289. if (WAIT_OBJECT_0 == WaitForSingleObject (TaskData.hExitEvent, 0))
  290. {
  291. goto DONE; // we're asked to exit
  292. }
  293. FD_ZERO (&readFDS);
  294. // Note: strategy used in this block to assign a value
  295. // to "fLen" is important for Solaris and benign for Win32
  296. FD_SET (tSock, &readFDS);
  297. fLen = (int)tSock;
  298. fLen++;
  299. // Must preserve value of fLen across loops
  300. nSock = select (fLen, &readFDS, NULL, NULL, &tvTimeout);
  301. if (0 == nSock)
  302. {
  303. // timeout
  304. continue;
  305. }
  306. else if (nSock == SOCKET_ERROR || *pSock == INVALID_SOCKET)
  307. {
  308. goto DONE; // terminate thread
  309. }
  310. // Only one socket monitored per thread, hence
  311. // FD_ISSET can be safely assumed at this point
  312. nSock = ioctlsocket (tSock, FIONREAD, &iBytes);
  313. if (nSock == SOCKET_ERROR || *pSock == INVALID_SOCKET)
  314. goto DONE;
  315. // Find the message buffer address...
  316. rMsgPtr = GlobalAlloc (GPTR, iBytes);
  317. if (rMsgPtr == NULL)
  318. { // No space error...throw away the message...
  319. recvfrom (tSock, (LPSTR)&nSock, 1, 0, NULL, NULL);
  320. if (*pSock == INVALID_SOCKET)
  321. goto DONE;
  322. // ...and call it quits.
  323. continue;
  324. }
  325. nSock = sizeof(SAS);
  326. // get the datagram and the address of the host that sent it
  327. iBytes = recvfrom (tSock, rMsgPtr, iBytes, 0, (LPSOCKADDR)&host, &nSock);
  328. if (iBytes != SOCKET_ERROR && *pSock != INVALID_SOCKET)
  329. MsgNotify (NP_RESPONSE, rMsgPtr, iBytes, 0, &host);
  330. else
  331. GlobalFree(rMsgPtr); // BUG# 458343
  332. } // end_while
  333. DONE:
  334. return (0);
  335. } // end_thrManager
  336. THR_TYPE WINAPI thrTimer (LPVOID nTask)
  337. { // Clean-up any timed-out messages
  338. BOOL bFree;
  339. DWORD lTicks, nMsg;
  340. DWORD nFound;
  341. SOCKET tSock;
  342. LPSNMPMSG pMsg;
  343. // This thread won't be needed immediately upon creation.
  344. // It sleeps/suspends itself as appropriate.
  345. // SnmpSendMsg() resumes it for each message sent
  346. // SnmpCleanup() resumes it to signal termination.
  347. while (TRUE)
  348. {// Once per second granularity
  349. Sleep (1000);
  350. // Check for termination request
  351. if (TaskData.timerThread == NULL)
  352. goto DONE;
  353. // If no msgs, go back to sleep
  354. if (MsgDescr.Used == 0)
  355. continue;
  356. EnterCriticalSection (&cs_MSG);
  357. for (nMsg=0, nFound=0; nFound<MsgDescr.Used && nMsg<MsgDescr.Allocated; nMsg++)
  358. {
  359. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  360. if (!pMsg->Session) // Skip unused slots
  361. continue;
  362. nFound++; // Signal break when last used slot is processed
  363. if (pMsg->Status != NP_SENT) // Skip pending and
  364. continue; // received messages
  365. lTicks = GetTickCount(); // update current time
  366. // Following test revised on 10/18/96 by BobN
  367. // Message "tick-time" rather than "TTL" now stored in MSG
  368. // to enable test for Windows timer wrap (49.7 days)
  369. // pMsg->PolicyTries - pMsg->Tries is the number of retries so far
  370. if ((pMsg->PolicyTries - pMsg->Tries+1)*pMsg->Wait + pMsg->Ticks > lTicks && // MSG TTL test
  371. pMsg->Ticks <= lTicks) // Timer wrap test
  372. continue; // Retain the message
  373. bFree = TRUE; // Prepare to free the message slot
  374. if (pMsg->nRetransmitMode)
  375. {
  376. if (pMsg->Tries)
  377. {
  378. LPENTITY pEntity;
  379. //WriteSocket (nMsg);
  380. // Determine which socket to use
  381. if (pMsg->Host.ipx.sa_family == AF_IPX)
  382. tSock = TaskData.ipxSock;
  383. else
  384. tSock = TaskData.ipSock;
  385. // Send the data
  386. sendto (tSock, pMsg->Addr, pMsg->Size,
  387. 0, (LPSOCKADDR)&(pMsg->Host), sizeof(SAS));
  388. // Need to check for SOCKET_ERROR!
  389. // end_WriteSocket
  390. //pMsg->Ticks is the time for the first SnmpSendMessage
  391. pMsg->Tries--; // Record the attempt
  392. // update the destination entity's nActualRetry
  393. EnterCriticalSection (&cs_ENTITY);
  394. // locate the agent (source) entity here
  395. pEntity = snmpGetTableEntry(&EntsDescr, HandleToUlong(pMsg->agentEntity)-1);
  396. // update the nActualRetry param of the agent (source) entity
  397. pEntity->nActualRetry = pMsg->PolicyTries - pMsg->Tries;
  398. LeaveCriticalSection (&cs_ENTITY);
  399. if (!pMsg->Tries) // No further retries?
  400. { // Release buffer space
  401. GlobalFree (pMsg->Addr);
  402. pMsg->Addr = NULL;
  403. pMsg->Size = 0;
  404. }
  405. bFree = FALSE; // Retain the message slot
  406. }
  407. else
  408. {
  409. LPSESSION pSession;
  410. pSession = snmpGetTableEntry(&SessDescr, HandleToUlong(pMsg->Session) - 1);
  411. if (pSession->fCallBack)
  412. { // callback session notification mode
  413. EnterCriticalSection (&cs_SESSION);
  414. if (pSession->thrHandle)
  415. {
  416. bFree = FALSE; // thrNotify will free it
  417. pMsg->Status = NP_EXPIRED;
  418. if (pSession->thrCount != 0xFFFFFFFF)
  419. pSession->thrCount++;
  420. SetEvent (pSession->thrEvent);
  421. }
  422. LeaveCriticalSection (&cs_SESSION);
  423. }
  424. else
  425. { // windows/message session notification mode
  426. if (IsWindow(pSession->hWnd))
  427. {
  428. PostMessage (pSession->hWnd,
  429. pSession->wMsg,
  430. SNMPAPI_TL_TIMEOUT,
  431. pMsg->appReqId);
  432. }
  433. }
  434. } // end_else (no retry left)
  435. } // end_if (retransmitMode)
  436. if (bFree) FreeMsg (nMsg);
  437. } // end_for
  438. LeaveCriticalSection (&cs_MSG);
  439. } // end_while
  440. DONE:
  441. return (0);
  442. } // end_thrTimer
  443. // Client side trap processing for Win32
  444. THR_TYPE WINAPI thrTrap (LPVOID lpTask)
  445. {
  446. #define TRAPBUFSIZE 4096
  447. typedef struct
  448. {
  449. SOCKADDR Addr;
  450. int AddrLen;
  451. UINT TrapBufSz;
  452. char TrapBuf[TRAPBUFSIZE];
  453. } SNMP_TRAP, *PSNMP_TRAP;
  454. SNMP_TRAP recvTrap;
  455. DWORD iBytes;
  456. smiLPBYTE rMsgPtr;
  457. BOOL bSuccess;
  458. //
  459. // Approach differs for NT (SNMPTRAP) vs '95
  460. //
  461. if (TaskData.sEnv.dwPlatformId == VER_PLATFORM_WIN32_NT)
  462. {
  463. // IMPORTANT NOTE FOR NT:
  464. // This code must be consistent with the SNMPTRAP code
  465. // wrt TRAPBUFSIZE, SNMPTRAPPIPE, and the SNMP_TRAP struct
  466. while (TRUE)
  467. {
  468. // check if thread termination required, Bug# 270672
  469. if (WAIT_OBJECT_0 == WaitForSingleObject (TaskData.trapEvent, 0))
  470. {
  471. break;
  472. }
  473. if (ReadFile(
  474. TaskData.trapPipe,
  475. (LPBYTE)&recvTrap,
  476. sizeof(SNMP_TRAP) - sizeof(recvTrap.TrapBuf), // message header size
  477. &iBytes,
  478. &TaskData.trapOl))
  479. {
  480. // It is impossible for ReadFile to succeed because
  481. // the specified number of bytes to read is less than
  482. // the size of the next message.
  483. break;
  484. }
  485. else
  486. {
  487. if (ERROR_IO_PENDING == GetLastError())
  488. {
  489. // block to wait until the reading of pipe message header completes
  490. // or we need to exit this thread
  491. bSuccess = GetOverlappedResult(
  492. TaskData.trapPipe,
  493. &TaskData.trapOl,
  494. &iBytes,
  495. TRUE); // Block
  496. // check if thread termination required
  497. if (WAIT_OBJECT_0 == WaitForSingleObject (TaskData.trapEvent, 0))
  498. {
  499. break;
  500. }
  501. // reset event to non-signaled state for next I/O
  502. ResetEvent(TaskData.trapOl.hEvent);
  503. if (!bSuccess)
  504. {
  505. if (ERROR_MORE_DATA != GetLastError())
  506. {
  507. break;
  508. }
  509. // we are here because the last overlapped read completes but we supplied
  510. // a smaller buffer than the pipe message, we'll read the rest of the message
  511. // below.
  512. }
  513. }
  514. else if (ERROR_MORE_DATA != GetLastError())
  515. {
  516. break;
  517. }
  518. }
  519. // Find the message buffer address...
  520. rMsgPtr = GlobalAlloc (GPTR, 2*recvTrap.TrapBufSz);
  521. if (rMsgPtr == NULL)
  522. {
  523. // No space error: E_OUTOFMEMORY
  524. break;
  525. }
  526. // read the rest of the pipe message
  527. if (
  528. !ReadFile(
  529. TaskData.trapPipe,
  530. (LPBYTE)rMsgPtr,
  531. 2*recvTrap.TrapBufSz,
  532. &iBytes,
  533. &TaskData.trapOl))
  534. {
  535. if (ERROR_IO_PENDING == GetLastError())
  536. {
  537. // block to wait until the reading of pipe message body completes
  538. // or we need to exit this thread
  539. bSuccess = GetOverlappedResult(
  540. TaskData.trapPipe,
  541. &TaskData.trapOl,
  542. &iBytes,
  543. TRUE); // Block
  544. // check if thread termination required
  545. if (WAIT_OBJECT_0 == WaitForSingleObject (TaskData.trapEvent, 0))
  546. {
  547. GlobalFree(rMsgPtr);
  548. break;
  549. }
  550. // reset event to non-signaled state for next I/O
  551. ResetEvent(TaskData.trapOl.hEvent);
  552. if (!bSuccess)
  553. {
  554. GlobalFree(rMsgPtr);
  555. break;
  556. }
  557. }
  558. else
  559. {
  560. GlobalFree(rMsgPtr);
  561. break;
  562. }
  563. }
  564. // get the datagram and the address of the host that sent it
  565. MsgNotify (NP_TRAP, rMsgPtr, iBytes, 0, (LPSAS)&recvTrap.Addr);
  566. } // end while()
  567. } // end_NT_thrTrap
  568. return (0);
  569. } // end_Win32_thrTrap
  570. THR_TYPE WINAPI thrAgent (LPVOID newAgent)
  571. {
  572. DWORD iBytes;
  573. int iLen;
  574. fd_set readFDS;
  575. SAS host;
  576. smiLPBYTE rMsgPtr;
  577. DWORD nAgent = (DWORD)((DWORD_PTR)newAgent);
  578. SOCKET sAgent = ((LPAGENT)snmpGetTableEntry(&AgentDescr, nAgent))->Socket;
  579. // fLen logic needed for Solaris; ignored in Win32
  580. int fLen = (int)sAgent + 1;
  581. while (TRUE)
  582. {
  583. FD_ZERO (&readFDS);
  584. FD_SET (sAgent, &readFDS);
  585. // Must preserve value of fLen acroos loops
  586. iLen = select (fLen, &readFDS, NULL, NULL, NULL);
  587. if (iLen == SOCKET_ERROR)
  588. goto DONE;
  589. // Only one socket per thread, therefore
  590. // we can safely assume FD_ISSET here
  591. iLen = ioctlsocket (sAgent, FIONREAD, &iBytes);
  592. if (iLen == SOCKET_ERROR)
  593. goto DONE;
  594. if (iBytes == 0)
  595. continue;
  596. // Find the message buffer address...
  597. rMsgPtr = GlobalAlloc (GPTR, iBytes);
  598. if (rMsgPtr == NULL)
  599. { // No space error...throw away the message...
  600. recvfrom (sAgent, (LPSTR)&iLen, 1, 0, NULL, NULL);
  601. // ...and call it quits.
  602. continue;
  603. }
  604. iLen = sizeof(SAS);
  605. // get the datagram and the address of the host that sent it
  606. iBytes = recvfrom (sAgent, rMsgPtr, iBytes, 0, (LPSOCKADDR)&host, &iLen);
  607. if (iBytes != SOCKET_ERROR)
  608. MsgNotify (NP_REQUEST, rMsgPtr, iBytes, nAgent, &host);
  609. else
  610. GlobalFree(rMsgPtr);
  611. } // end_while
  612. DONE:
  613. return (0);
  614. } // end_thrAgent
  615. BOOL MapV1TrapV2 (LPPDUS pdu)
  616. {
  617. LPVARBIND VbTicks = NULL;
  618. LPVARBIND VbTrap = NULL;
  619. LPVARBIND VbAddress = NULL;
  620. LPVARBIND VbEnterprise = NULL;
  621. LPVARBIND endPtr;
  622. smiLPUINT32 ptrTrap;
  623. smiUINT32 lenTrap;
  624. if (!pdu)
  625. return (FALSE);
  626. // Adjust "generic" for v2 values
  627. pdu->v1Trap->generic_trap++; // as oid in v2 is v1 # +1
  628. if (pdu->v1Trap->generic_trap == 7) // specific?
  629. pdu->v1Trap->generic_trap = 0; // v2
  630. // rfc1908:(2) If a Trap-PDU is received, then it is mapped into a
  631. // SNMPv2-Trap-PDU. This is done by prepending onto the variable-bindings
  632. // field two new bindings: sysUpTime.0 [12], which takes its value from the
  633. // timestamp field of the Trap-PDU; and.......
  634. if (!(VbTicks = (LPVARBIND)GlobalAlloc (GPTR, sizeof(VARBIND))))
  635. return (FALSE);
  636. if (SnmpOidCopy (&sysUpTimeName, &VbTicks->name) == SNMPAPI_FAILURE)
  637. goto ERROROUT;
  638. VbTicks->value.syntax = SNMP_SYNTAX_TIMETICKS;
  639. VbTicks->value.value.uNumber = pdu->v1Trap->time_ticks;
  640. // ..... snmpTrapOID.0 [13], which is calculated thusly: if the value of
  641. // generic-trap field is `enterpriseSpecific', then the value used is the
  642. // concatenation of the enterprise field from the Trap-PDU with two additional
  643. // sub-identifiers, `0', and the value of the specific-trap field; otherwise,
  644. // the value of the corresponding trap defined in [13] is used. (For example,
  645. // if the value of the generic-trap field is `coldStart', then the coldStart
  646. // trap [13] is used.)
  647. if (!(VbTrap = (LPVARBIND)GlobalAlloc (GPTR, sizeof(VARBIND))))
  648. goto ERROROUT;
  649. if (SnmpOidCopy (&snmpTrapOidName, &VbTrap->name) == SNMPAPI_FAILURE)
  650. goto ERROROUT;
  651. VbTrap->value.syntax = SNMP_SYNTAX_OID;
  652. if (snmpTrapsValue[9] = pdu->v1Trap->generic_trap) // Deliberate assignment
  653. { // SNMP_TRAP_GENERIC
  654. lenTrap = sizeof(snmpTrapsValue);
  655. VbTrap->value.value.oid.len = lenTrap / sizeof(smiUINT32);
  656. ptrTrap = snmpTrapsValue;
  657. }
  658. else
  659. { // SNMP_TRAP_ENTERPRISE
  660. lenTrap = pdu->v1Trap->enterprise.len * sizeof(smiUINT32);
  661. VbTrap->value.value.oid.len = pdu->v1Trap->enterprise.len + 2;
  662. ptrTrap = pdu->v1Trap->enterprise.ptr;
  663. }
  664. if (!(VbTrap->value.value.oid.ptr = (smiLPUINT32)GlobalAlloc
  665. (GPTR, VbTrap->value.value.oid.len * sizeof(smiUINT32))))
  666. goto ERROROUT;
  667. CopyMemory (VbTrap->value.value.oid.ptr, ptrTrap, lenTrap);
  668. if (!pdu->v1Trap->generic_trap)
  669. { // SNMP_TRAP_ENTERPRISE
  670. VbTrap->value.value.oid.ptr[pdu->v1Trap->enterprise.len+1] =
  671. pdu->v1Trap->specific_trap;
  672. }
  673. // Special code to retain v1Trap AgentAddress info in an experimental object
  674. // This is *not* part of the WinSNMP v2.0 standard at this time (6/25/98)
  675. if (TaskData.conveyAddress != SNMPAPI_ON)
  676. goto DO_ENTERPRISE;
  677. if (!(VbAddress = (LPVARBIND)GlobalAlloc (GPTR, sizeof(VARBIND))))
  678. goto ERROROUT;
  679. if (SnmpOidCopy (&snmpTrapAddrName, &VbAddress->name) == SNMPAPI_FAILURE)
  680. goto ERROROUT;
  681. VbAddress->value.syntax = SNMP_SYNTAX_IPADDR;
  682. // *Re-use* this OID parsed in WSNMP_BN code
  683. VbAddress->value.value.string.len = pdu->v1Trap->agent_addr.len;
  684. VbAddress->value.value.string.ptr = pdu->v1Trap->agent_addr.ptr;
  685. pdu->v1Trap->agent_addr.len = 0; // Setting .ptr to NULL required
  686. pdu->v1Trap->agent_addr.ptr = NULL; // for later call to FreeV1Trap()
  687. DO_ENTERPRISE:
  688. // Then,......one new binding is appended onto the variable-bindings field:
  689. // snmpTrapEnterpriseOID.0 [13], which takes its value from the enterprise field
  690. // of the Trap-PDU.
  691. //
  692. // WINSNMP specs in SnmpRecvMsg specifies this append for both the generic and
  693. // specific traps and not only for specific as RFC 1452 does.
  694. if (!(VbEnterprise = (LPVARBIND)GlobalAlloc (GPTR, sizeof(VARBIND))))
  695. goto ERROROUT;
  696. if (SnmpOidCopy (&snmpTrapEntName, &VbEnterprise->name) == SNMPAPI_FAILURE)
  697. goto ERROROUT;
  698. VbEnterprise->value.syntax = SNMP_SYNTAX_OID;
  699. // *Re-use* this OID parsed in WSNMP_BN code
  700. VbEnterprise->value.value.oid.len = pdu->v1Trap->enterprise.len;
  701. VbEnterprise->value.value.oid.ptr = pdu->v1Trap->enterprise.ptr;
  702. pdu->v1Trap->enterprise.len = 0; // Setting .ptr to NULL required
  703. pdu->v1Trap->enterprise.ptr = NULL; // for later call to FreeV1Trap()
  704. //We have all the variables set, just need to link them together
  705. //backup the head of the original vbs
  706. endPtr = pdu->VBL_addr;
  707. // setup the new head of the list
  708. pdu->VBL_addr = VbTicks;
  709. VbTicks->next_var = VbTrap;
  710. VbTrap->next_var = endPtr;
  711. // position endPtr on the last varbind from the list
  712. if (endPtr != NULL)
  713. {
  714. // set it on the last varbind from the original V1 trap
  715. while (endPtr->next_var != NULL)
  716. endPtr = endPtr->next_var;
  717. }
  718. else
  719. {
  720. // set it on VbTrap if no varbinds were passed in the V1 trap
  721. endPtr = VbTrap;
  722. }
  723. // append VbAddress if any and set endPtr on the new ending
  724. if (VbAddress != NULL)
  725. {
  726. endPtr->next_var = VbAddress;
  727. endPtr = VbAddress;
  728. }
  729. // append VbEnterprise
  730. endPtr->next_var = VbEnterprise;
  731. VbEnterprise->next_var = NULL;
  732. //
  733. // make it say it's an SNMPv2 Trap PDU
  734. pdu->type = SNMP_PDU_TRAP;
  735. // Assign a RequestID (not in SNMPv1 Trap PDUs (no need to lock)
  736. pdu->appReqId = ++(TaskData.nLastReqId);
  737. return (TRUE);
  738. //
  739. ERROROUT:
  740. // Free only those resources created in this function
  741. // FreeVarBind is a noop on NULLs, so no need to check first
  742. FreeVarBind (VbEnterprise);
  743. FreeVarBind (VbAddress);
  744. FreeVarBind (VbTrap);
  745. FreeVarBind (VbTicks);
  746. return (FALSE);
  747. } // end_MapV1TrapV2
  748. BOOL DispatchTrap (LPSAS host, smiLPOCTETS community, LPPDUS pdu)
  749. {
  750. #define MAXSLOTS 10 // maximum active trap receivers
  751. DWORD nCmp;
  752. DWORD nFound = 0;
  753. DWORD nTrap = 0;
  754. DWORD nTraps[MAXSLOTS];
  755. DWORD nMsg = 0;
  756. LPSNMPMSG pMsg;
  757. LPTRAPNOTICE pTrap;
  758. EnterCriticalSection (&cs_TRAP);
  759. for (nTrap = 0; nTrap < TrapDescr.Allocated; nTrap++)
  760. {
  761. pTrap = snmpGetTableEntry(&TrapDescr, nTrap);
  762. if (!pTrap->Session) continue; // Active trap registration and
  763. if (pTrap->notification.len) // all Traps?
  764. { // Nope, specific test
  765. SNMPAPI_STATUS lError;
  766. // Next line is critical...do not remove...BN 3/8/96
  767. pTrap->notification.ptr = &(pTrap->notificationValue[0]);
  768. // 2nd param below assumes well-formed trap/inform...BN 1/21/97
  769. lError = SnmpOidCompare (&(pTrap->notification),
  770. &pdu->VBL_addr->next_var->value.value.oid,
  771. pTrap->notification.len, &nCmp);
  772. if (lError != SNMPAPI_SUCCESS || nCmp) continue; // not equal...
  773. }
  774. if (pTrap->agentEntity) // Specific agent?
  775. {
  776. int nResult;
  777. LPENTITY pEntity = snmpGetTableEntry(&EntsDescr, HandleToUlong(pTrap->agentEntity) - 1);
  778. if (host->ipx.sa_family == AF_IPX)
  779. nResult = memcmp (&host->ipx.sa_netnum,
  780. &(pEntity->addr.ipx.sa_netnum), AF_IPX_ADDR_SIZE);
  781. else // AF_IPX
  782. nResult = memcmp (&host->inet.sin_addr,
  783. &(pEntity->addr.inet.sin_addr), AF_INET_ADDR_SIZE);
  784. if (nResult)
  785. continue; // not equal...
  786. }
  787. if (pTrap->Context) // Specific context?
  788. {
  789. LPCTXT pCtxt = snmpGetTableEntry(&CntxDescr, HandleToUlong(pTrap->Context) - 1);
  790. if (community->len != pCtxt->commLen)
  791. continue; // not equal...lengths
  792. if (memcmp (community->ptr, pCtxt->commStr,
  793. (size_t)community->len))
  794. continue; // not equal...values
  795. }
  796. nTraps[nFound] = nTrap; // Got a match!
  797. nFound++; // Count the number found and check it against maximums
  798. if ((nFound == (MAXSLOTS)) || (nFound == TrapDescr.Used))
  799. break;
  800. } // end_for
  801. LeaveCriticalSection (&cs_TRAP);
  802. if (nFound == 0) // Nothing to do
  803. return (SNMPAPI_FAILURE);
  804. //
  805. nCmp = nFound; // Save count for later user
  806. EnterCriticalSection (&cs_MSG);
  807. while (nFound)
  808. {
  809. DWORD lError;
  810. lError = snmpAllocTableEntry(&MsgDescr, &nMsg);
  811. if (lError != SNMPAPI_SUCCESS)
  812. {
  813. LeaveCriticalSection(&cs_MSG);
  814. return lError;
  815. }
  816. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  817. --nFound;
  818. nTrap = nTraps[nFound];
  819. nTraps[nFound] = nMsg; // Need for later use
  820. pTrap = snmpGetTableEntry(&TrapDescr, nTrap);
  821. pMsg->Session = pTrap->Session;
  822. pMsg->Status = NP_RCVD;
  823. pMsg->Type = pdu->type;
  824. // 960522 - BN...
  825. // Need to increment the eventual "dstEntity" if
  826. // one was specified on the SnmpRegister() filter (unusual).
  827. // Deliberate assignment...
  828. if (pMsg->ourEntity = pTrap->ourEntity)
  829. {
  830. LPENTITY pEntity = snmpGetTableEntry(&EntsDescr, HandleToUlong(pTrap->ourEntity)-1);
  831. pEntity->refCount++;
  832. }
  833. // end_960522 - BN
  834. pMsg->dllReqId = pMsg->appReqId = pdu->appReqId;
  835. pMsg->Ticks = pMsg->Tries = pMsg->PolicyTries = 0;
  836. CopyMemory (&(pMsg->Host), host, sizeof(SAS));
  837. if (!(BuildMessage (1, community, pdu, pdu->appReqId,
  838. &(pMsg->Addr), &(pMsg->Size))))
  839. {
  840. // rollback for all messages from nCmp to nFound
  841. while (nCmp != nFound)
  842. {
  843. nMsg = nTraps[--nCmp];
  844. FreeMsg (nMsg);
  845. }
  846. LeaveCriticalSection (&cs_MSG);
  847. return (SNMPAPI_PDU_INVALID);
  848. }
  849. } // end_while (nFound)
  850. LeaveCriticalSection (&cs_MSG);
  851. //
  852. // The next while loop actually sends the one or more trap messages
  853. // to the application(s)...
  854. // This is due to the fact that we "clone" the incoming trap msg
  855. // if there are multiple registrations for it. BobN 2/20/95
  856. while (nCmp) // Saved message count
  857. { // Now actually send the message(s)
  858. LPSESSION pSession;
  859. nMsg = nTraps[--nCmp];
  860. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  861. pSession = snmpGetTableEntry(&SessDescr, HandleToUlong(pMsg->Session) - 1);
  862. if (pSession->fCallBack)
  863. { // callback session notification mode
  864. EnterCriticalSection (&cs_SESSION);
  865. if (pSession->thrHandle)
  866. {
  867. if (pSession->thrCount != 0xFFFFFFFF)
  868. pSession->thrCount++;
  869. SetEvent (pSession->thrEvent);
  870. }
  871. else
  872. FreeMsg (nMsg);
  873. LeaveCriticalSection (&cs_SESSION);
  874. }
  875. else
  876. { // window/message session notification mode
  877. if (IsWindow(pSession->hWnd))
  878. {
  879. pMsg->Status = NP_READY;
  880. PostMessage (pSession->hWnd,
  881. pSession->wMsg, 0, 0L);
  882. }
  883. else
  884. FreeMsg (nMsg);
  885. }
  886. } // end_while (nCmp)
  887. return (SNMPAPI_SUCCESS);
  888. } // end_DispatchTrap
  889. LPPDUS MapV2TrapV1 (HSNMP_PDU hPdu)
  890. {
  891. // Convert SNMPv2 trap to SNMPv1 trap, for sending only
  892. HSNMP_VBL hNewVbl = NULL;
  893. LPPDUS oldPdu = NULL;
  894. LPPDUS newPdu = NULL;
  895. smiUINT32 lCount;
  896. smiUINT32 lCmp;
  897. smiUINT32 i;
  898. smiLPBYTE tmpPtr = NULL;
  899. smiOID sName;
  900. smiVALUE sValue;
  901. //
  902. if (hPdu == NULL)
  903. return (NULL);
  904. oldPdu = snmpGetTableEntry(&PDUsDescr, HandleToUlong(hPdu)-1);
  905. if (oldPdu->type != SNMP_PDU_TRAP)
  906. return (NULL);
  907. if (SnmpGetPduData (hPdu, NULL, NULL, NULL, NULL, &hNewVbl) == SNMPAPI_FAILURE)
  908. return (NULL);
  909. if (hNewVbl == NULL)
  910. return (NULL);
  911. newPdu = GlobalAlloc (GPTR, sizeof(PDUS));
  912. if (newPdu == NULL)
  913. goto ERR_OUT;
  914. // From RFC 2089
  915. // 3.3 Processing an outgoing SNMPv2 TRAP
  916. //
  917. // If SNMPv2 compliant instrumentation presents an SNMPv2 trap to the
  918. // SNMP engine and such a trap passes all regular checking and then is
  919. // to be sent to an SNMPv1 destination, then the following steps must be
  920. // followed to convert such a trap to an SNMPv1 trap. This is basically
  921. // the reverse of the SNMPv1 to SNMPv2 mapping as described in RFC1908
  922. // [3].
  923. newPdu->type = SNMP_PDU_V1TRAP;
  924. newPdu->v1Trap = GlobalAlloc (GPTR, sizeof(V1TRAP));
  925. if (newPdu->v1Trap == NULL)
  926. goto ERR_OUT;
  927. //
  928. // 1. If any of the varBinds in the varBindList has an SNMPv2 syntax
  929. // of Counter64, then such varBinds are implicitly considered to
  930. // be not in view, and so they are removed from the varBindList to
  931. // be sent with the SNMPv1 trap.
  932. //
  933. // We will do that step later, but check the VB count for now:
  934. lCount = SnmpCountVbl (hNewVbl); // SNMPAPI_FAILURE is 0
  935. // Need at least 2 for sysUptime and snmpTrapOID!
  936. if (lCount < 2)
  937. goto ERR_OUT;
  938. //
  939. // 2. The 3 special varBinds in the varBindList of an SNMPv2 trap
  940. // (sysUpTime.0 (TimeTicks), snmpTrapOID.0 (OBJECT IDENTIFIER) and
  941. // optionally snmpTrapEnterprise.0 (OBJECT IDENTIFIER)) are
  942. // removed from the varBindList to be sent with the SNMPv1 trap.
  943. // These 2 (or 3) varBinds are used to decide how to set other
  944. // fields in the SNMPv1 trap PDU as follows:
  945. //
  946. // a. The value of sysUpTime.0 is copied into the timestamp field
  947. // of the SNMPv1 trap.
  948. //
  949. if (SnmpGetVb (hNewVbl, 1, &sName, &sValue) == SNMPAPI_FAILURE)
  950. goto ERR_OUT;
  951. if (SnmpOidCompare (&sysUpTimeName, &sName, 0, &lCmp) == SNMPAPI_FAILURE)
  952. {
  953. // sValue is a number, no need to free
  954. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sName);
  955. goto ERR_OUT;
  956. }
  957. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sName); // ignore error
  958. if (lCmp != 0)
  959. goto ERR_OUT;
  960. newPdu->v1Trap->time_ticks = sValue.value.uNumber;
  961. if (SnmpDeleteVb (hNewVbl, 1) == SNMPAPI_FAILURE)
  962. goto ERR_OUT;
  963. lCount--;
  964. //
  965. // b. If the snmpTrapOID.0 value is one of the standard traps
  966. // the specific-trap field is set to zero and the generic
  967. // trap field is set according to this mapping:
  968. //
  969. // value of snmpTrapOID.0 generic-trap
  970. // =============================== ============
  971. // 1.3.6.1.6.3.1.1.5.1 (coldStart) 0
  972. // 1.3.6.1.6.3.1.1.5.2 (warmStart) 1
  973. // 1.3.6.1.6.3.1.1.5.3 (linkDown) 2
  974. // 1.3.6.1.6.3.1.1.5.4 (linkUp) 3
  975. // 1.3.6.1.6.3.1.1.5.5 (authenticationFailure) 4
  976. // 1.3.6.1.6.3.1.1.5.6 (egpNeighborLoss) 5
  977. //
  978. if (SnmpGetVb (hNewVbl, 1, &sName, &sValue) == SNMPAPI_FAILURE)
  979. goto ERR_OUT;
  980. if (SnmpOidCompare (&snmpTrapOidName, &sName, 0, &lCmp) == SNMPAPI_FAILURE)
  981. {
  982. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sName);
  983. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sValue.value.oid);
  984. goto ERR_OUT;
  985. }
  986. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sName); // ignore error
  987. if (lCmp != 0)
  988. {
  989. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sValue.value.oid);
  990. goto ERR_OUT;
  991. }
  992. if (SnmpOidCompare (&snmpTrapsName, &sValue.value.oid, 9, &lCmp) == SNMPAPI_FAILURE)
  993. {
  994. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sValue.value.oid);
  995. goto ERR_OUT;
  996. }
  997. if (!lCmp)
  998. {
  999. newPdu->v1Trap->generic_trap = sValue.value.oid.ptr[9] - 1;
  1000. newPdu->v1Trap->specific_trap = 0;
  1001. // The enterprise field is set to the value of
  1002. // snmpTrapEnterprise.0 if this varBind is present, otherwise
  1003. // it is set to the value snmpTraps as defined in RFC1907 [4].
  1004. i = snmpTrapsName.len - 1;
  1005. tmpPtr = (smiLPBYTE)snmpTrapsValue;
  1006. }
  1007. //
  1008. // c. If the snmpTrapOID.0 value is not one of the standard
  1009. // traps, then the generic-trap field is set to 6 and the
  1010. // specific-trap field is set to the last subid of the
  1011. // snmpTrapOID.0 value.
  1012. else
  1013. {
  1014. newPdu->v1Trap->generic_trap = 6;
  1015. i = sValue.value.oid.len;
  1016. newPdu->v1Trap->specific_trap = sValue.value.oid.ptr[i-1];
  1017. tmpPtr = (smiLPBYTE)sValue.value.oid.ptr;
  1018. //
  1019. // o If the next to last subid of snmpTrapOID.0 is zero,
  1020. // then the enterprise field is set to snmpTrapOID.0 value
  1021. // and the last 2 subids are truncated from that value.
  1022. if (sValue.value.oid.ptr[i-2] == 0)
  1023. i -= 2;
  1024. // o If the next to last subid of snmpTrapOID.0 is not zero,
  1025. // then the enterprise field is set to snmpTrapOID.0 value
  1026. // and the last 1 subid is truncated from that value.
  1027. else
  1028. i -= 1;
  1029. // In any event, the snmpTrapEnterprise.0 varBind (if present)
  1030. // is ignored in this case.
  1031. }
  1032. //
  1033. newPdu->v1Trap->enterprise.len = i;
  1034. i *= sizeof(smiUINT32);
  1035. // This allocation might have to be freed later,
  1036. // if generic trap and SnmpTrapEnterprise.0 is present in the varbindlist.
  1037. newPdu->v1Trap->enterprise.ptr = GlobalAlloc (GPTR, i);
  1038. if (newPdu->v1Trap->enterprise.ptr == NULL)
  1039. {
  1040. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sValue.value.oid);
  1041. goto ERR_OUT;
  1042. }
  1043. CopyMemory (newPdu->v1Trap->enterprise.ptr, tmpPtr, i);
  1044. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sValue.value.oid); // ignore error
  1045. if (SnmpDeleteVb (hNewVbl, 1) == SNMPAPI_FAILURE)
  1046. goto ERR_OUT;
  1047. lCount--;
  1048. //
  1049. i = 1;
  1050. while (i <= lCount)
  1051. {
  1052. if (SnmpGetVb (hNewVbl, i, &sName, &sValue) == SNMPAPI_FAILURE)
  1053. goto ERR_OUT;
  1054. if (sValue.syntax == SNMP_SYNTAX_CNTR64)
  1055. {
  1056. if (SnmpDeleteVb (hNewVbl, i) == SNMPAPI_FAILURE)
  1057. goto ERR_LOOP;
  1058. lCount--;
  1059. goto LOOP;
  1060. }
  1061. if (SnmpOidCompare (&snmpTrapEntName, &sName, 0, &lCmp) == SNMPAPI_FAILURE)
  1062. goto ERR_LOOP;
  1063. if (lCmp == 0)
  1064. {
  1065. if (newPdu->v1Trap->specific_trap == 0)
  1066. {
  1067. if (newPdu->v1Trap->enterprise.ptr)
  1068. GlobalFree (newPdu->v1Trap->enterprise.ptr);
  1069. lCmp = sValue.value.oid.len * sizeof(smiUINT32);
  1070. newPdu->v1Trap->enterprise.ptr = GlobalAlloc (GPTR, lCmp);
  1071. if (newPdu->v1Trap->enterprise.ptr == NULL)
  1072. goto ERR_LOOP;
  1073. newPdu->v1Trap->enterprise.len = sValue.value.oid.len;
  1074. CopyMemory (newPdu->v1Trap->enterprise.ptr,
  1075. sValue.value.oid.ptr, lCmp);
  1076. }
  1077. if (SnmpDeleteVb (hNewVbl, i) == SNMPAPI_FAILURE)
  1078. goto ERR_LOOP;
  1079. lCount--;
  1080. goto LOOP;
  1081. }
  1082. i++;
  1083. LOOP:
  1084. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sName);
  1085. SnmpFreeDescriptor (sValue.syntax, (smiLPOPAQUE)&sValue.value.oid);
  1086. }
  1087. goto DONE_LOOP; // jump over error handling code
  1088. ERR_LOOP:
  1089. SnmpFreeDescriptor (SNMP_SYNTAX_OID, (smiLPOPAQUE)&sName);
  1090. SnmpFreeDescriptor (sValue.syntax, (smiLPOPAQUE)&sValue.value.oid);
  1091. goto ERR_OUT;
  1092. DONE_LOOP:
  1093. if (lCount > 0)
  1094. {
  1095. LPVBLS pVbl = snmpGetTableEntry(&VBLsDescr, HandleToUlong(hNewVbl)-1);
  1096. // Retain existing varbindlist remainder
  1097. newPdu->VBL_addr = pVbl->vbList;
  1098. // Flag it as gone for subsequent call to SnmpFreeVbl
  1099. pVbl->vbList = NULL;
  1100. }
  1101. SnmpFreeVbl (hNewVbl);
  1102. //
  1103. // 3. The agent-addr field is set with the appropriate address of the
  1104. // the sending SNMP entity, which is the IP address of the sending
  1105. // entity of the trap goes out over UDP; otherwise the agent-addr
  1106. // field is set to address 0.0.0.0.
  1107. newPdu->v1Trap->agent_addr.len = sizeof(DWORD);
  1108. newPdu->v1Trap->agent_addr.ptr = GlobalAlloc (GPTR, sizeof(DWORD));
  1109. if (newPdu->v1Trap->agent_addr.ptr == NULL)
  1110. goto ERR_OUT;
  1111. if (TaskData.localAddress == 0)
  1112. { // Get the local machine address (for outgoing v1 traps)
  1113. char szLclHost [MAX_HOSTNAME];
  1114. LPHOSTENT lpstHostent;
  1115. if (gethostname (szLclHost, MAX_HOSTNAME) != SOCKET_ERROR)
  1116. {
  1117. lpstHostent = gethostbyname ((LPSTR)szLclHost);
  1118. if (lpstHostent)
  1119. TaskData.localAddress = *((LPDWORD)(lpstHostent->h_addr));
  1120. }
  1121. }
  1122. *(LPDWORD)newPdu->v1Trap->agent_addr.ptr = TaskData.localAddress;
  1123. // end_RFC2089
  1124. return (newPdu);
  1125. //
  1126. ERR_OUT:
  1127. SnmpFreeVbl (hNewVbl);
  1128. if (newPdu)
  1129. {
  1130. FreeVarBindList (newPdu->VBL_addr); // Checks for NULL
  1131. FreeV1Trap (newPdu->v1Trap); // Checks for NULL
  1132. GlobalFree (newPdu);
  1133. }
  1134. return (NULL);
  1135. } // end_MapV2TrapV1