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.

1551 lines
46 KiB

  1. // wsnmp_cf.c
  2. //
  3. // WinSNMP Communications Functions and helpers
  4. // Copyright 1995-1998 ACE*COMM Corp
  5. // Rleased to Microsoft under Contract
  6. //
  7. // Bob Natale ([email protected])
  8. //
  9. // 19980625 - Modified SnmpStartup() to allow for NULL
  10. // output args and to check for IsBadWritePtr()
  11. // when non-NULL
  12. //
  13. #include "winsnmp.inc"
  14. #define SNMP_MAJOR_VERSION 2
  15. #define SNMP_MINOR_VERSION 0
  16. #define SNMP_SUPPORT_LEVEL SNMPAPI_V2_SUPPORT
  17. LPPDUS MapV2TrapV1 (HSNMP_PDU hPdu);
  18. THR_TYPE WINAPI thrManager (LPVOID);
  19. THR_TYPE WINAPI thrTrap (LPVOID);
  20. THR_TYPE WINAPI thrTimer (LPVOID);
  21. THR_TYPE WINAPI thrAgent (LPVOID);
  22. THR_TYPE WINAPI thrNotify (LPVOID);
  23. void FreeRegister (DWORD nTrap)
  24. {
  25. LPTRAPNOTICE pTrap;
  26. EnterCriticalSection (&cs_TRAP);
  27. pTrap = snmpGetTableEntry(&TrapDescr, nTrap);
  28. if (pTrap->ourEntity)
  29. SnmpFreeEntity (pTrap->ourEntity);
  30. if (pTrap->agentEntity)
  31. SnmpFreeEntity (pTrap->agentEntity);
  32. if (pTrap->Context)
  33. SnmpFreeContext (pTrap->Context);
  34. snmpFreeTableEntry(&TrapDescr, nTrap);
  35. LeaveCriticalSection (&cs_TRAP);
  36. return;
  37. } // end_FreeRegister
  38. // Exported Functions
  39. // SnmpStartup
  40. SNMPAPI_STATUS SNMPAPI_CALL
  41. SnmpStartup (OUT smiLPUINT32 nMajorVersion,
  42. OUT smiLPUINT32 nMinorVersion,
  43. OUT smiLPUINT32 nLevel,
  44. OUT smiLPUINT32 nTranslateMode,
  45. OUT smiLPUINT32 nRetransmitMode)
  46. {
  47. WSADATA wsaData;
  48. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  49. HSNMP_SESSION hTask = (HSNMP_SESSION) ULongToPtr(GetCurrentProcessId());
  50. //
  51. //
  52. if (nMajorVersion)
  53. {
  54. if (IsBadWritePtr (nMajorVersion, sizeof(smiUINT32)))
  55. goto ARG_ERROR;
  56. *nMajorVersion = SNMP_MAJOR_VERSION;
  57. }
  58. if (nMinorVersion)
  59. {
  60. if (IsBadWritePtr (nMinorVersion, sizeof(smiUINT32)))
  61. goto ARG_ERROR;
  62. *nMinorVersion = SNMP_MINOR_VERSION;
  63. }
  64. if (nLevel)
  65. {
  66. if (IsBadWritePtr (nLevel, sizeof(smiUINT32)))
  67. goto ARG_ERROR;
  68. *nLevel = SNMP_SUPPORT_LEVEL;
  69. }
  70. if (nTranslateMode)
  71. {
  72. if (IsBadWritePtr (nTranslateMode, sizeof(smiUINT32)))
  73. goto ARG_ERROR;
  74. *nTranslateMode = SNMPAPI_UNTRANSLATED_V1;
  75. }
  76. if (nRetransmitMode)
  77. {
  78. if (IsBadWritePtr (nRetransmitMode, sizeof(smiUINT32)))
  79. goto ARG_ERROR;
  80. *nRetransmitMode = SNMPAPI_ON;
  81. }
  82. goto ARGS_OK;
  83. ARG_ERROR:
  84. lError = SNMPAPI_ALLOC_ERROR;
  85. goto ERROR_OUT;
  86. ARGS_OK:
  87. EnterCriticalSection (&cs_TASK);
  88. TaskData.nRetransmitMode = SNMPAPI_ON;
  89. TaskData.nTranslateMode = SNMPAPI_UNTRANSLATED_V1;
  90. // we need to turn this on in order to have WINSNMP to pass back not
  91. // only the entity standing for the source Ip address but also the
  92. // agent address as it was sent into the V1 Trap Pdu.
  93. TaskData.conveyAddress = SNMPAPI_ON;
  94. // SnmpStartup is idempotent...
  95. if (TaskData.hTask == hTask)
  96. goto DONE; // ...already called
  97. // New task starting up...get OS info
  98. TaskData.sEnv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  99. if (!GetVersionEx (&TaskData.sEnv))
  100. {
  101. lError = SNMPAPI_OTHER_ERROR;
  102. goto ERROR_PRECHECK;
  103. }
  104. // Start WinSock connection...should return 0
  105. if (WSAStartup ((WORD)0x0101, &wsaData))
  106. {
  107. lError = SNMPAPI_TL_NOT_INITIALIZED;
  108. goto ERROR_PRECHECK;
  109. }
  110. // Set trapPipe (used in NT case only)
  111. TaskData.trapPipe = INVALID_HANDLE_VALUE;
  112. // bug# 270672
  113. // create non-signaled event to synchronize shutdown of thrTrap
  114. TaskData.trapEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  115. if (NULL == TaskData.trapEvent)
  116. {
  117. lError = SNMPAPI_ALLOC_ERROR;
  118. WSACleanup();
  119. goto ERROR_PRECHECK;
  120. }
  121. // init the trapOl overlapped struct with manual reset non-signaled event
  122. ZeroMemory(&TaskData.trapOl, sizeof(TaskData.trapOl));
  123. TaskData.trapOl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  124. if (NULL == TaskData.trapOl.hEvent)
  125. {
  126. lError = SNMPAPI_ALLOC_ERROR;
  127. CloseHandle(TaskData.trapEvent);
  128. TaskData.trapEvent = NULL;
  129. WSACleanup();
  130. goto ERROR_PRECHECK;
  131. }
  132. // init TaskData.hExitEvent with manual reset non-signaled event to
  133. // synchronize shutdown of thrManager
  134. TaskData.hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  135. if (NULL == TaskData.hExitEvent)
  136. {
  137. lError = SNMPAPI_ALLOC_ERROR;
  138. CloseHandle(TaskData.trapEvent);
  139. TaskData.trapEvent = NULL;
  140. CloseHandle(TaskData.trapOl.hEvent);
  141. TaskData.trapOl.hEvent = NULL;
  142. WSACleanup();
  143. goto ERROR_PRECHECK;
  144. }
  145. // Set trapSock (used in Win95 case only)
  146. TaskData.trapSock = INVALID_SOCKET;
  147. // Set "manager" sockets (used at SnmpSendMsg() time)
  148. TaskData.ipSock = TaskData.ipxSock = INVALID_SOCKET;
  149. // Start timer thread
  150. {
  151. DWORD thrId;
  152. TaskData.timerThread = (HANDLE)_beginthreadex (NULL, 0, thrTimer, NULL, 0, &thrId);
  153. if (NULL == TaskData.timerThread)
  154. {
  155. lError = SNMPAPI_TL_RESOURCE_ERROR;
  156. CloseHandle(TaskData.trapEvent);
  157. TaskData.trapEvent = NULL;
  158. CloseHandle(TaskData.trapOl.hEvent);
  159. TaskData.trapOl.hEvent = NULL;
  160. WSACleanup();
  161. goto ERROR_PRECHECK;
  162. }
  163. }
  164. //
  165. DONE:
  166. TaskData.hTask = hTask;
  167. TaskData.nLastError = SNMPAPI_SUCCESS;
  168. ERROR_PRECHECK:
  169. LeaveCriticalSection (&cs_TASK);
  170. if (lError == SNMPAPI_SUCCESS)
  171. return (SNMPAPI_SUCCESS);
  172. ERROR_OUT:
  173. return (SaveError (0, lError));
  174. } // end_SnmpStartup
  175. // SnmpCleanup
  176. SNMPAPI_STATUS SNMPAPI_CALL SnmpCleanup (void)
  177. {
  178. DWORD nSession;
  179. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  180. // Variables for threads not associated with a specific session
  181. DWORD nHandles = 0;
  182. HANDLE hTemp[4] = {NULL, NULL, NULL, NULL};
  183. CONST HANDLE *hObjects = &hTemp[0];
  184. //--------------------------------------------------------------
  185. if (TaskData.hTask == 0)
  186. {
  187. lError = SNMPAPI_NOT_INITIALIZED;
  188. goto ERROR_OUT;
  189. }
  190. EnterCriticalSection (&cs_SESSION);
  191. // Do all Forgotten Closes
  192. if (SessDescr.Used)
  193. {
  194. for (nSession = 0; nSession < SessDescr.Allocated; nSession++)
  195. if (((LPSESSION)snmpGetTableEntry(&SessDescr, nSession))->nTask)
  196. SnmpClose ((HSNMP_SESSION) ULongToPtr(nSession + 1));
  197. }
  198. LeaveCriticalSection (&cs_SESSION);
  199. EnterCriticalSection (&cs_TASK);
  200. SetEvent(TaskData.hExitEvent); // askes thrManager to exit
  201. // Terminate thrTimer
  202. if (TaskData.timerThread)
  203. {
  204. hTemp[nHandles++] = TaskData.timerThread;
  205. // NULL signals the timer thread to terminate itself
  206. TaskData.timerThread = NULL;
  207. }
  208. // Close "Mgr" sockets and threads
  209. if (TaskData.ipSock != INVALID_SOCKET)
  210. {// UDP channel
  211. // check thrManager code to understand the lines below:
  212. SOCKET ipSock = TaskData.ipSock;
  213. WaitForSingleObject (TaskData.ipThread, INFINITE);
  214. TaskData.ipSock = INVALID_SOCKET;
  215. closesocket (ipSock);
  216. if (TaskData.ipThread)
  217. hTemp[nHandles++] = TaskData.ipThread;
  218. }
  219. if (TaskData.ipxSock != INVALID_SOCKET)
  220. {// IPX channel
  221. // check thrManager code to understand the lines below:
  222. SOCKET ipxSock = TaskData.ipxSock;
  223. WaitForSingleObject (TaskData.ipxThread, INFINITE);
  224. TaskData.ipxSock = INVALID_SOCKET;
  225. closesocket (ipxSock);
  226. if (TaskData.ipxThread)
  227. hTemp[nHandles++] = TaskData.ipxThread;
  228. }
  229. // Terminate thrTrap
  230. if (TaskData.trapThread)
  231. {
  232. if (TaskData.sEnv.dwPlatformId == VER_PLATFORM_WIN32_NT)
  233. { // NT-specific stuff
  234. // set events to signal thrTrap to exit
  235. SetEvent(TaskData.trapEvent);
  236. // unblock thrTrap if necessary
  237. SetEvent(TaskData.trapOl.hEvent);
  238. }
  239. hTemp[nHandles++] = TaskData.trapThread;
  240. }
  241. WaitForMultipleObjects (nHandles, hObjects, TRUE, 5000);
  242. while (nHandles > 0)
  243. {
  244. nHandles--;
  245. CloseHandle (hTemp[nHandles]);
  246. }
  247. if (TaskData.trapPipe != INVALID_HANDLE_VALUE)
  248. CloseHandle (TaskData.trapPipe);
  249. if (TaskData.trapEvent != NULL)
  250. CloseHandle(TaskData.trapEvent);
  251. if (TaskData.trapOl.hEvent != NULL)
  252. CloseHandle(TaskData.trapOl.hEvent);
  253. if (TaskData.hExitEvent)
  254. CloseHandle(TaskData.hExitEvent);
  255. // Do the main thing
  256. ZeroMemory (&TaskData, sizeof(TASK));
  257. LeaveCriticalSection (&cs_TASK);
  258. // Close down WinSock connection
  259. WSACleanup ();
  260. //
  261. //
  262. return (SNMPAPI_SUCCESS);
  263. ERROR_OUT:
  264. return (SaveError (0, lError));
  265. } // end_SnmpCleanup
  266. // Open a session (v1 and v2)
  267. HSNMP_SESSION SNMPAPI_CALL SnmpOpen (IN HWND hWnd, IN UINT wMsg)
  268. {
  269. return (SnmpCreateSession (hWnd, wMsg, NULL, NULL));
  270. } // end_SnmpOpen
  271. // Open a session, w/callback option (v2)
  272. HSNMP_SESSION SNMPAPI_CALL
  273. SnmpCreateSession (IN HWND hWnd, IN UINT wMsg,
  274. IN SNMPAPI_CALLBACK fCallBack,
  275. IN LPVOID lpClientData)
  276. {
  277. DWORD nSession;
  278. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  279. LPSESSION pSession;
  280. if (TaskData.hTask == 0)
  281. {
  282. lError = SNMPAPI_NOT_INITIALIZED;
  283. goto ERROR_OUT;
  284. }
  285. // Check for window/message notification mode argument validity
  286. if (fCallBack == NULL)
  287. if (!IsWindow(hWnd))
  288. {
  289. lError = SNMPAPI_HWND_INVALID;
  290. goto ERROR_OUT;
  291. }
  292. //
  293. EnterCriticalSection (&cs_SESSION);
  294. lError = snmpAllocTableEntry(&SessDescr, &nSession);
  295. if (lError != SNMPAPI_SUCCESS)
  296. goto ERROR_PRECHECK;
  297. pSession = snmpGetTableEntry(&SessDescr, nSession);
  298. pSession->nTask = TaskData.hTask;
  299. pSession->hWnd = hWnd;
  300. pSession->wMsg = wMsg;
  301. pSession->fCallBack = fCallBack;
  302. pSession->lpClientData = lpClientData;
  303. if (fCallBack)
  304. {
  305. DWORD thrId;
  306. pSession->thrEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  307. if (NULL == pSession->thrEvent)
  308. {
  309. lError = SNMPAPI_ALLOC_ERROR;
  310. snmpFreeTableEntry(&SessDescr, nSession);
  311. goto ERROR_PRECHECK;
  312. }
  313. pSession->thrCount = 0;
  314. pSession->thrHandle = (HANDLE)_beginthreadex
  315. (NULL, 0, thrNotify, (LPVOID) ULongToPtr(nSession), 0, &thrId);
  316. if (NULL == pSession->thrHandle)
  317. {
  318. lError = SNMPAPI_TL_RESOURCE_ERROR;
  319. snmpFreeTableEntry(&SessDescr, nSession);
  320. CloseHandle(pSession->thrEvent);
  321. pSession->thrEvent = NULL;
  322. goto ERROR_PRECHECK;
  323. }
  324. }
  325. pSession->nLastError = SNMPAPI_SUCCESS;
  326. ERROR_PRECHECK:
  327. LeaveCriticalSection (&cs_SESSION);
  328. if (lError == SNMPAPI_SUCCESS)
  329. return ((HSNMP_SESSION) ULongToPtr(nSession+1));
  330. ERROR_OUT:
  331. return ((HSNMP_SESSION) ULongToPtr(SaveError (0, lError)));
  332. } // end_SnmpOpen
  333. // SnmpClose
  334. SNMPAPI_STATUS SNMPAPI_CALL
  335. SnmpClose (IN HSNMP_SESSION hSession)
  336. {
  337. HANDLE thrTemp;
  338. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  339. DWORD nSes = HandleToUlong(hSession) - 1;
  340. DWORD i;
  341. LPSESSION pSession;
  342. if (TaskData.hTask == 0)
  343. {
  344. lError = SNMPAPI_NOT_INITIALIZED;
  345. goto ERROR_OUT;
  346. }
  347. if (!snmpValidTableEntry(&SessDescr, nSes))
  348. {
  349. lError = SNMPAPI_SESSION_INVALID;
  350. goto ERROR_OUT;
  351. }
  352. pSession = snmpGetTableEntry(&SessDescr, nSes);
  353. // Strategy:
  354. // 1st: Stop notifications to session
  355. // 2nd: Stop accepting new messages
  356. // Traps
  357. // Agents
  358. // 3rd: Clear out pending messages
  359. // 4th: Free up all other resources
  360. //
  361. // PART_1: Stop notifications to the closing Session
  362. // Block window/message notification (in all cases!)
  363. pSession->hWnd = NULL;
  364. // Block callback notification (if required)
  365. if (pSession->fCallBack != NULL)
  366. {
  367. // Save thrHandle for WaitForSingleObject call
  368. EnterCriticalSection (&cs_SESSION);
  369. thrTemp = pSession->thrHandle;
  370. // If this is a callback session, must stop thrNotify instance
  371. pSession->thrHandle = NULL;
  372. // 0xFFFFFFFF signals thrNotify instance to terminate itself
  373. pSession->thrCount = 0xFFFFFFFF;
  374. // SetEvent signals thrNotify instance to run
  375. SetEvent (pSession->thrEvent);
  376. LeaveCriticalSection (&cs_SESSION);
  377. // Wait for termination signal from thread handle
  378. WaitForSingleObject (thrTemp, 30000);
  379. // Close thrNotify instance handle
  380. CloseHandle (thrTemp);
  381. // Close thrNotify event handle
  382. CloseHandle (pSession->thrEvent);
  383. }
  384. // PART_2: Stop accepting new messages for the closing Session
  385. // Free Notifications registered by the closing Session
  386. EnterCriticalSection (&cs_TRAP);
  387. for (i = 0; i < TrapDescr.Allocated && TrapDescr.Used != 0; i++)
  388. {
  389. LPTRAPNOTICE pTrap = snmpGetTableEntry(&TrapDescr, i);
  390. if (pTrap->Session == hSession)
  391. FreeRegister (i);
  392. } // end_for (Traps)
  393. LeaveCriticalSection (&cs_TRAP);
  394. // Free Agents registered by the closing Session
  395. EnterCriticalSection (&cs_AGENT);
  396. for (i = 0; i < AgentDescr.Allocated && AgentDescr.Used != 0; i++)
  397. {
  398. LPAGENT pAgent = snmpGetTableEntry(&AgentDescr, i);
  399. if (pAgent->Session == hSession)
  400. SnmpListen (pAgent->Entity, SNMPAPI_OFF);
  401. }
  402. LeaveCriticalSection (&cs_AGENT);
  403. // PART_3: Free all pending messages for the closing Session
  404. EnterCriticalSection (&cs_MSG);
  405. for (i = 0; i < MsgDescr.Allocated && MsgDescr.Used != 0; i++)
  406. {
  407. LPSNMPMSG pMsg = snmpGetTableEntry(&MsgDescr, i);
  408. if (pMsg->Session == hSession)
  409. FreeMsg (i);
  410. }
  411. LeaveCriticalSection (&cs_MSG);
  412. // PART_4: Free all other resources
  413. // Free Entities allocated by the closing Session
  414. EnterCriticalSection (&cs_ENTITY);
  415. for (i = 0; i < EntsDescr.Allocated && EntsDescr.Used != 0; i++)
  416. {
  417. LPENTITY pEntity = snmpGetTableEntry(&EntsDescr, i);
  418. if (pEntity->Session == hSession)
  419. SnmpFreeEntity ((HSNMP_ENTITY) ULongToPtr(i+1));
  420. }
  421. LeaveCriticalSection (&cs_ENTITY);
  422. // Free Contexts allocated by the closing Session
  423. EnterCriticalSection (&cs_CONTEXT);
  424. for (i = 0; i < CntxDescr.Allocated && CntxDescr.Used != 0; i++)
  425. {
  426. LPCTXT pCtxt = snmpGetTableEntry(&CntxDescr, i);
  427. if (pCtxt->Session == hSession)
  428. SnmpFreeContext ((HSNMP_CONTEXT) ULongToPtr(i+1));
  429. }
  430. LeaveCriticalSection (&cs_CONTEXT);
  431. // Free VBLs allocated by the closing Session
  432. EnterCriticalSection (&cs_VBL);
  433. for (i = 0; i < VBLsDescr.Allocated && VBLsDescr.Used != 0; i++)
  434. {
  435. LPVBLS pVbl = snmpGetTableEntry(&VBLsDescr, i);
  436. if (pVbl->Session == hSession)
  437. SnmpFreeVbl ((HSNMP_VBL) ULongToPtr(i+1));
  438. }
  439. LeaveCriticalSection (&cs_VBL);
  440. // Free PDUs allocated by the closing Session
  441. EnterCriticalSection (&cs_PDU);
  442. for (i = 0; i < PDUsDescr.Allocated && PDUsDescr.Used != 0; i++)
  443. {
  444. LPPDUS pPDU = snmpGetTableEntry(&PDUsDescr, i);
  445. if (pPDU->Session == hSession)
  446. SnmpFreePdu ((HSNMP_PDU) ULongToPtr(i+1));
  447. }
  448. LeaveCriticalSection (&cs_PDU);
  449. // Free the Session table entry used by the closing Session
  450. EnterCriticalSection (&cs_SESSION);
  451. snmpFreeTableEntry(&SessDescr, nSes);
  452. LeaveCriticalSection (&cs_SESSION);
  453. return (SNMPAPI_SUCCESS);
  454. ERROR_OUT:
  455. // As of 19980808 there are no error cases with a valid session
  456. return (SaveError (0, lError));
  457. } // end_SnmpClose
  458. // SnmpSendMsg
  459. SNMPAPI_STATUS SNMPAPI_CALL
  460. SnmpSendMsg (IN HSNMP_SESSION hSession,
  461. IN HSNMP_ENTITY hSrc,
  462. IN HSNMP_ENTITY hDst,
  463. IN HSNMP_CONTEXT hCtx,
  464. IN HSNMP_PDU hPdu)
  465. {
  466. LPPDUS sendPdu;
  467. BOOL fMsg;
  468. DWORD nMsg;
  469. DWORD pduType;
  470. smiINT32 dllReqId;
  471. smiOCTETS tmpContext;
  472. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  473. HSNMP_SESSION lSession = 0;
  474. //
  475. DWORD thrId;
  476. SOCKET *pSock;
  477. int tFamily;
  478. SOCKADDR tAddr;
  479. HANDLE *pThread;
  480. //
  481. DWORD nSrc;
  482. DWORD nDst;
  483. DWORD nCtx;
  484. DWORD nPdu;
  485. //
  486. BOOL fBroadcast;
  487. //
  488. LPPDUS pPdu;
  489. LPENTITY pEntSrc, pEntDst;
  490. LPCTXT pCtxt;
  491. LPSNMPMSG pMsg;
  492. if (TaskData.hTask == 0)
  493. {
  494. lError = SNMPAPI_NOT_INITIALIZED;
  495. goto ERROR_OUT;
  496. }
  497. if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1))
  498. {
  499. lError = SNMPAPI_SESSION_INVALID;
  500. goto ERROR_OUT;
  501. }
  502. // Save valid session for later error returns
  503. lSession = hSession;
  504. if (hSrc) // Allowed to be NULL
  505. {
  506. nSrc = HandleToUlong(hSrc) - 1;
  507. if (!snmpValidTableEntry(&EntsDescr, nSrc))
  508. {
  509. lError = SNMPAPI_ENTITY_INVALID;
  510. goto ERROR_OUT;
  511. }
  512. pEntSrc = snmpGetTableEntry(&EntsDescr, nSrc);
  513. }
  514. nDst = HandleToUlong(hDst) - 1;
  515. if (!snmpValidTableEntry(&EntsDescr, nDst))
  516. {
  517. lError = SNMPAPI_ENTITY_INVALID;
  518. goto ERROR_OUT;
  519. }
  520. pEntDst = snmpGetTableEntry(&EntsDescr, nDst);
  521. nCtx = HandleToUlong(hCtx) - 1;
  522. if (!snmpValidTableEntry(&CntxDescr, nCtx))
  523. {
  524. lError = SNMPAPI_CONTEXT_INVALID;
  525. goto ERROR_OUT;
  526. }
  527. pCtxt = snmpGetTableEntry(&CntxDescr, nCtx);
  528. nPdu = HandleToUlong(hPdu) - 1;
  529. if (!snmpValidTableEntry(&PDUsDescr, nPdu))
  530. {
  531. lError = SNMPAPI_PDU_INVALID;
  532. goto ERROR_OUT;
  533. }
  534. pPdu = snmpGetTableEntry(&PDUsDescr, nPdu);
  535. if (!snmpValidTableEntry(&VBLsDescr, HandleToUlong(pPdu->VBL)-1))
  536. {
  537. lError = SNMPAPI_VBL_INVALID;
  538. goto ERROR_OUT;
  539. }
  540. //--------------
  541. tFamily = pEntDst->addr.inet.sin_family;
  542. // enter the critical section for the TaskData structure to insure
  543. // the atomicity of the Test&Set operation of the TaskData.[ip|ipx]Thread
  544. EnterCriticalSection (&cs_TASK);
  545. pThread = (tFamily==AF_IPX) ? &TaskData.ipxThread : &TaskData.ipThread;
  546. pSock = (tFamily==AF_IPX) ? &TaskData.ipxSock : &TaskData.ipSock;
  547. if (*pThread) // ASSERT(*pSock != INVALID_SOCKET)
  548. {
  549. LeaveCriticalSection(&cs_TASK);
  550. goto CHANNEL_OPEN;
  551. }
  552. *pSock = socket (tFamily, SOCK_DGRAM, (tFamily==AF_IPX)?NSPROTO_IPX:0);
  553. if (*pSock == INVALID_SOCKET)
  554. {
  555. LeaveCriticalSection(&cs_TASK);
  556. lError = SNMPAPI_TL_NOT_SUPPORTED;
  557. goto ERROR_OUT;
  558. }
  559. // try to set the socket for broadcasts. No matter the result
  560. // a possible error will be caught later
  561. // The following setsockopt call will be removed in Longhorn
  562. fBroadcast = TRUE;
  563. setsockopt (*pSock,
  564. SOL_SOCKET,
  565. SO_BROADCAST,
  566. (CHAR *) &fBroadcast,
  567. sizeof ( BOOL )
  568. );
  569. // Kludge for Win95 WinSock/IPX bug...have to "bind"
  570. ZeroMemory (&tAddr, sizeof(SOCKADDR));
  571. tAddr.sa_family = (USHORT)tFamily;
  572. bind (*pSock, &tAddr, (tFamily==AF_IPX)?sizeof(SOCKADDR_IPX):sizeof(SOCKADDR_IN));
  573. // Start "listener" and timer threads
  574. *pThread = (HANDLE)_beginthreadex (NULL, 0, thrManager, (LPVOID)pSock, 0, &thrId);
  575. if (*pThread == NULL)
  576. {
  577. closesocket (*pSock);
  578. *pSock = INVALID_SOCKET;
  579. lError = SNMPAPI_TL_RESOURCE_ERROR;
  580. LeaveCriticalSection (&cs_TASK);
  581. goto ERROR_OUT;
  582. }
  583. LeaveCriticalSection (&cs_TASK);
  584. //---------------
  585. CHANNEL_OPEN:
  586. pduType = pPdu->type;
  587. sendPdu = pPdu;
  588. if (pEntDst->version == 1)
  589. { // Test for special v2 msg -> v1 dst operations
  590. if (pduType == SNMP_PDU_TRAP)
  591. { // RFC 2089 v2 to v1 trap conversion
  592. sendPdu = MapV2TrapV1 (hPdu);
  593. if (sendPdu == NULL)
  594. {
  595. lError = SNMPAPI_OTHER_ERROR;
  596. goto ERROR_OUT;
  597. }
  598. pduType = SNMP_PDU_V1TRAP;
  599. }
  600. else if (pduType == SNMP_PDU_INFORM)
  601. {
  602. lError = SNMPAPI_OPERATION_INVALID;
  603. goto ERROR_OUT;
  604. }
  605. }
  606. // Space check
  607. EnterCriticalSection (&cs_MSG);
  608. lError = snmpAllocTableEntry(&MsgDescr, &nMsg);
  609. if (lError != SNMPAPI_SUCCESS)
  610. goto ERROR_PRECHECK;
  611. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  612. // Now Build it
  613. if (pduType == SNMP_PDU_RESPONSE || pduType == SNMP_PDU_TRAP)
  614. dllReqId = pPdu->appReqId;
  615. else
  616. dllReqId = ++(TaskData.nLastReqId);
  617. tmpContext.len = pCtxt->commLen;
  618. tmpContext.ptr = pCtxt->commStr;
  619. // Save BuildMessage status for later check
  620. fMsg = BuildMessage (pEntDst->version-1, &tmpContext, sendPdu,
  621. dllReqId, &(pMsg->Addr), &(pMsg->Size));
  622. // If v2 to v1 trap conversion was required, then cleanup...
  623. if (pduType == SNMP_PDU_V1TRAP)
  624. {
  625. FreeVarBindList (sendPdu->VBL_addr); // Checks for NULL
  626. FreeV1Trap (sendPdu->v1Trap); // Checks for NULL
  627. GlobalFree (sendPdu);
  628. }
  629. // If BuildMessage failed, that's all folks!
  630. if (!fMsg)
  631. {
  632. snmpFreeTableEntry(&MsgDescr, nMsg);
  633. lError = SNMPAPI_PDU_INVALID;
  634. goto ERROR_PRECHECK;
  635. }
  636. pMsg->Session = hSession;
  637. pMsg->Status = NP_SEND; // "send"
  638. pMsg->Type = pduType;
  639. pMsg->nRetransmitMode = TaskData.nRetransmitMode;
  640. pMsg->dllReqId = dllReqId;
  641. pMsg->appReqId = pPdu->appReqId;
  642. pMsg->agentEntity = hDst;
  643. pMsg->ourEntity = hSrc;
  644. pMsg->Context = hCtx;
  645. LeaveCriticalSection (&cs_MSG);
  646. // Update reference counts for entities and contexts,
  647. EnterCriticalSection (&cs_ENTITY);
  648. if (hSrc)
  649. pEntSrc->refCount++;
  650. pEntDst->refCount++;
  651. LeaveCriticalSection (&cs_ENTITY);
  652. EnterCriticalSection (&cs_CONTEXT);
  653. pCtxt->refCount++;
  654. LeaveCriticalSection (&cs_CONTEXT);
  655. // Prepare addressing info for traps
  656. EnterCriticalSection (&cs_MSG);
  657. CopyMemory (&(pMsg->Host), &pEntDst->addr, sizeof(SAS));
  658. if (pduType == SNMP_PDU_V1TRAP ||
  659. pduType == SNMP_PDU_TRAP ||
  660. pduType == SNMP_PDU_INFORM)
  661. {
  662. if (tFamily == AF_IPX)
  663. {
  664. if (pMsg->Host.ipx.sa_socket == ntohs (IPX_SNMP_PORT))
  665. pMsg->Host.ipx.sa_socket = htons (IPX_TRAP_PORT);
  666. }
  667. else // Assume AF_INET
  668. {
  669. if (pMsg->Host.inet.sin_port == ntohs (IP_SNMP_PORT))
  670. pMsg->Host.inet.sin_port = htons(IP_TRAP_PORT);
  671. }
  672. }
  673. // Send the packet
  674. thrId = sendto (*pSock, pMsg->Addr, pMsg->Size,
  675. 0, (LPSOCKADDR)&(pMsg->Host), sizeof(SAS));
  676. if (thrId == SOCKET_ERROR)
  677. {
  678. FreeMsg (nMsg);
  679. lError = SNMPAPI_TL_OTHER;
  680. goto ERROR_PRECHECK;
  681. }
  682. // Need to check for SOCKET_ERROR!
  683. if (pduType == SNMP_PDU_TRAP ||
  684. pduType == SNMP_PDU_V1TRAP ||
  685. pduType == SNMP_PDU_RESPONSE)
  686. {
  687. FreeMsg (nMsg);
  688. }
  689. else
  690. {
  691. pMsg->Status = NP_SENT;
  692. // Time entity's timeout value is stored as centiseconds in 32 bits
  693. pMsg->Wait = pEntDst->nPolicyTimeout;
  694. // Converting to milliseconds for timer operations could overflow
  695. if (pMsg->Wait <= MAXCENTISECONDS) // So check first...if ok
  696. pMsg->Wait *= 10; // Convert to milliseconds
  697. else // eles...
  698. pMsg->Wait = MAXMILLISECONDS; // Set to max milliseconds
  699. pMsg->Tries = pMsg->PolicyTries = pEntDst->nPolicyRetry;
  700. pMsg->Ticks = GetTickCount();
  701. }
  702. ERROR_PRECHECK:
  703. LeaveCriticalSection (&cs_MSG);
  704. if (lError == SNMPAPI_SUCCESS)
  705. return (SNMPAPI_SUCCESS);
  706. ERROR_OUT:
  707. return (SaveError (lSession, lError));
  708. } // end_SnmpSendMsg
  709. // SnmpRecvMsg
  710. SNMPAPI_STATUS SNMPAPI_CALL
  711. SnmpRecvMsg (IN HSNMP_SESSION hSession,
  712. OUT LPHSNMP_ENTITY srcEntity,
  713. OUT LPHSNMP_ENTITY dstEntity,
  714. OUT LPHSNMP_CONTEXT context,
  715. OUT LPHSNMP_PDU pdu)
  716. {
  717. DWORD nMsg;
  718. DWORD nPdu;
  719. int pduType;
  720. smiLPOCTETS community;
  721. smiUINT32 version;
  722. smiUINT32 nMode;
  723. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  724. HSNMP_SESSION lSession = 0;
  725. DWORD nSes = HandleToUlong(hSession) - 1;
  726. LPPDUS pPdu;
  727. LPENTITY pEntity;
  728. LPSNMPMSG pMsg;
  729. DWORD lTime; // holds the local time for updating the nActualTimeout value
  730. if (TaskData.hTask == 0)
  731. {
  732. lError = SNMPAPI_NOT_INITIALIZED;
  733. goto ERROR_OUT;
  734. }
  735. if (!snmpValidTableEntry(&SessDescr, nSes))
  736. {
  737. lError = SNMPAPI_SESSION_INVALID;
  738. goto ERROR_OUT;
  739. }
  740. // Valid session...save for possible error return
  741. lSession = hSession;
  742. EnterCriticalSection (&cs_MSG);
  743. // Find a message for the calling session
  744. for (nMsg = 0; nMsg < MsgDescr.Allocated; nMsg++)
  745. {
  746. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  747. if (pMsg->Session == hSession &&
  748. pMsg->Status == NP_READY)
  749. break;
  750. }
  751. if (nMsg == MsgDescr.Allocated)
  752. {
  753. lError = SNMPAPI_NOOP;
  754. goto ERROR_PRECHECK1;
  755. }
  756. if (!pMsg->Addr)
  757. {
  758. lError = SNMPAPI_MESSAGE_INVALID;
  759. goto ERROR_PRECHECK1;
  760. }
  761. ERROR_PRECHECK1:
  762. LeaveCriticalSection (&cs_MSG);
  763. if (lError != SNMPAPI_SUCCESS)
  764. goto ERROR_OUT;
  765. // Allocate a slot in PDU table
  766. EnterCriticalSection (&cs_PDU);
  767. lError = snmpAllocTableEntry(&PDUsDescr, &nPdu);
  768. if (lError != SNMPAPI_SUCCESS)
  769. goto ERROR_PRECHECK2;
  770. pPdu = snmpGetTableEntry(&PDUsDescr, nPdu);
  771. nMode = ParseMessage (pMsg->Addr, pMsg->Size,
  772. &version, &community, pPdu);
  773. if (nMode != 0) // non-zero = error code
  774. {
  775. snmpFreeTableEntry(&PDUsDescr, nPdu);
  776. FreeMsg (nMsg);
  777. lError = SNMPAPI_PDU_INVALID;
  778. goto ERROR_PRECHECK2;
  779. }
  780. pPdu->Session = hSession;
  781. pPdu->appReqId = pMsg->appReqId;
  782. ERROR_PRECHECK2:
  783. LeaveCriticalSection (&cs_PDU);
  784. if (lError != SNMPAPI_SUCCESS)
  785. goto ERROR_OUT;
  786. pduType = pPdu->type;
  787. EnterCriticalSection (&cs_ENTITY);
  788. // for RESPONSE messages only, update the 'ActualRetry' and 'ActualTimeout' parameters
  789. // for all the other messages, these params are meaningless
  790. if (pduType == SNMP_PDU_RESPONSE)
  791. {
  792. // locate the agent (source) entity here
  793. pEntity = snmpGetTableEntry(&EntsDescr, HandleToUlong(pMsg->agentEntity)-1);
  794. // update the nActualTimeout param of the agent (source) entity.
  795. lTime = GetTickCount();
  796. if (pMsg->Ticks > lTime)
  797. // handle the time wrap case
  798. // (~pMsg->Ticks + 1) is 2's complement of pMsg->Ticks
  799. pEntity->nActualTimeout = (lTime + ~pMsg->Ticks + 1)/10;
  800. else
  801. pEntity->nActualTimeout = (lTime - pMsg->Ticks)/10;
  802. // update the nActualRetry param of the agent (source) entity
  803. pEntity->nActualRetry = pMsg->PolicyTries - pMsg->Tries;
  804. }
  805. if (srcEntity)
  806. {
  807. if (pduType == SNMP_PDU_TRAP ||
  808. pduType == SNMP_PDU_INFORM ||
  809. pduType != SNMP_PDU_RESPONSE)
  810. {
  811. int afType = pMsg->Host.ipx.sa_family;
  812. char afHost[MAX_PATH+1];
  813. afHost[MAX_PATH] = '\0';
  814. EnterCriticalSection (&cs_XMODE);
  815. SnmpGetTranslateMode (&nMode);
  816. SnmpSetTranslateMode (SNMPAPI_UNTRANSLATED_V1);
  817. if (afType == AF_IPX)
  818. SnmpIpxAddressToStr (pMsg->Host.ipx.sa_netnum,
  819. pMsg->Host.ipx.sa_nodenum,
  820. afHost);
  821. else // AF_INET
  822. {
  823. char * pszIpAddr;
  824. pszIpAddr = inet_ntoa (pMsg->Host.inet.sin_addr);
  825. if (NULL == pszIpAddr)
  826. {
  827. LeaveCriticalSection (&cs_XMODE);
  828. lError = SNMPAPI_TL_OTHER;
  829. goto ERROR_PRECHECK3;
  830. }
  831. strncpy (afHost, pszIpAddr, MAX_PATH);
  832. }
  833. if ((pMsg->agentEntity = SnmpStrToEntity (hSession, afHost)) == SNMPAPI_FAILURE)
  834. {
  835. LeaveCriticalSection (&cs_XMODE);
  836. lError = SNMPAPI_OTHER_ERROR;
  837. goto ERROR_PRECHECK3;
  838. }
  839. pEntity = snmpGetTableEntry(&EntsDescr, HandleToUlong(pMsg->agentEntity)-1);
  840. if (afType == AF_IPX)
  841. pEntity->addr.ipx.sa_socket = pMsg->Host.ipx.sa_socket;
  842. else // AF_INET
  843. pEntity->addr.inet.sin_port = pMsg->Host.inet.sin_port;
  844. SnmpSetTranslateMode (nMode);
  845. LeaveCriticalSection (&cs_XMODE);
  846. }
  847. // Deliberate assignment...
  848. if (*srcEntity = pMsg->agentEntity)
  849. {
  850. pEntity = snmpGetTableEntry(&EntsDescr, HandleToUlong(pMsg->agentEntity)-1);
  851. pEntity->refCount++;
  852. }
  853. }
  854. if (dstEntity)
  855. { // Deliberate assignment...
  856. if (*dstEntity = pMsg->ourEntity)
  857. {
  858. pEntity = snmpGetTableEntry(&EntsDescr, HandleToUlong(pMsg->ourEntity)-1);
  859. pEntity->refCount++;
  860. }
  861. }
  862. ERROR_PRECHECK3:
  863. LeaveCriticalSection (&cs_ENTITY);
  864. if (lError != SNMPAPI_SUCCESS)
  865. {
  866. FreeOctetString (community);
  867. SnmpFreePdu ((HSNMP_PDU) ULongToPtr(nPdu+1));
  868. FreeMsg (nMsg);
  869. goto ERROR_OUT;
  870. }
  871. EnterCriticalSection (&cs_CONTEXT);
  872. if (context)
  873. {
  874. if (pduType == SNMP_PDU_TRAP ||
  875. pduType == SNMP_PDU_INFORM ||
  876. pduType != SNMP_PDU_RESPONSE)
  877. {
  878. EnterCriticalSection (&cs_XMODE);
  879. SnmpGetTranslateMode (&nMode);
  880. SnmpSetTranslateMode (SNMPAPI_UNTRANSLATED_V1);
  881. if ((pMsg->Context = SnmpStrToContext (hSession, community)) == SNMPAPI_FAILURE)
  882. {
  883. LeaveCriticalSection (&cs_XMODE);
  884. lError = SNMPAPI_OTHER_ERROR;
  885. goto ERROR_PRECHECK4;
  886. }
  887. SnmpSetTranslateMode (nMode);
  888. LeaveCriticalSection (&cs_XMODE);
  889. }
  890. // Deliberate assignment...
  891. if (*context = pMsg->Context)
  892. ((LPCTXT)snmpGetTableEntry(&CntxDescr, HandleToUlong(pMsg->Context)-1))->refCount++;
  893. }
  894. ERROR_PRECHECK4:
  895. LeaveCriticalSection (&cs_CONTEXT);
  896. if (lError != SNMPAPI_SUCCESS)
  897. {
  898. // rollback
  899. if (context && *context)
  900. {
  901. SnmpFreeContext(*context);
  902. *context = NULL;
  903. }
  904. if (dstEntity && *dstEntity)
  905. {
  906. SnmpFreeEntity(*dstEntity);
  907. *dstEntity = NULL;
  908. }
  909. if (srcEntity && *srcEntity)
  910. {
  911. SnmpFreeEntity(*srcEntity);
  912. *srcEntity = NULL;
  913. }
  914. FreeOctetString (community);
  915. SnmpFreePdu ((HSNMP_PDU) ULongToPtr(nPdu+1));
  916. FreeMsg (nMsg);
  917. goto ERROR_OUT;
  918. }
  919. FreeOctetString (community);
  920. if (pdu)
  921. *pdu = (HSNMP_PDU) ULongToPtr(nPdu+1);
  922. else
  923. SnmpFreePdu ((HSNMP_PDU) ULongToPtr(nPdu+1));
  924. // Mark SendRecv slot as free
  925. FreeMsg (nMsg);
  926. return (SNMPAPI_SUCCESS);
  927. ERROR_OUT:
  928. return (SaveError (lSession, lError));
  929. } // end_SnmpRecvMsg
  930. // Allocates a generic ACL to be used for the security descriptor of the SNMPTRAP service
  931. PACL AllocGenericACL()
  932. {
  933. PACL pAcl;
  934. PSID pSidAdmins, pSidUsers;
  935. SID_IDENTIFIER_AUTHORITY Authority = SECURITY_NT_AUTHORITY;
  936. DWORD dwAclLength;
  937. pSidAdmins = pSidUsers = NULL;
  938. if ( !AllocateAndInitializeSid( &Authority,
  939. 2,
  940. SECURITY_BUILTIN_DOMAIN_RID,
  941. DOMAIN_ALIAS_RID_ADMINS,
  942. 0, 0, 0, 0, 0, 0,
  943. &pSidAdmins ) )
  944. {
  945. return NULL;
  946. }
  947. if ( !AllocateAndInitializeSid( &Authority,
  948. 2,
  949. SECURITY_BUILTIN_DOMAIN_RID,
  950. DOMAIN_ALIAS_RID_USERS,
  951. 0, 0, 0, 0, 0, 0,
  952. &pSidUsers ))
  953. {
  954. FreeSid(pSidAdmins);
  955. return NULL;
  956. }
  957. dwAclLength = sizeof(ACL) +
  958. sizeof(ACCESS_ALLOWED_ACE) -
  959. sizeof(ULONG) +
  960. GetLengthSid(pSidAdmins) +
  961. sizeof(ACCESS_ALLOWED_ACE) -
  962. sizeof(ULONG) +
  963. GetLengthSid(pSidUsers);
  964. pAcl = GlobalAlloc (GPTR, dwAclLength);
  965. if (pAcl != NULL)
  966. {
  967. if (!InitializeAcl( pAcl, dwAclLength, ACL_REVISION) ||
  968. !AddAccessAllowedAce ( pAcl,
  969. ACL_REVISION,
  970. GENERIC_ALL,
  971. pSidAdmins ) ||
  972. !AddAccessAllowedAce ( pAcl,
  973. ACL_REVISION,
  974. GENERIC_READ | GENERIC_EXECUTE,
  975. pSidUsers ))
  976. {
  977. GlobalFree(pAcl);
  978. pAcl = NULL;
  979. }
  980. }
  981. FreeSid(pSidAdmins);
  982. FreeSid(pSidUsers);
  983. return pAcl;
  984. }
  985. // frees a generic ACL
  986. void FreeGenericACL( PACL pAcl)
  987. {
  988. if (pAcl != NULL)
  989. GlobalFree(pAcl);
  990. }
  991. // SnmpRegister
  992. SNMPAPI_STATUS SNMPAPI_CALL
  993. SnmpRegister (IN HSNMP_SESSION hSession,
  994. IN HSNMP_ENTITY hSrc,
  995. IN HSNMP_ENTITY hDst,
  996. IN HSNMP_CONTEXT hCtx,
  997. IN smiLPCOID notification,
  998. IN smiUINT32 status)
  999. {
  1000. DWORD nNotice, nFound;
  1001. smiINT32 nCmp;
  1002. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  1003. HSNMP_SESSION lSession = 0;
  1004. DWORD nSes = HandleToUlong(hSession) - 1;
  1005. DWORD nSrc;
  1006. DWORD nDst;
  1007. DWORD nCtx;
  1008. LPENTITY pEntSrc, pEntDst;
  1009. LPCTXT pCtxt;
  1010. LPTRAPNOTICE pTrap;
  1011. if (TaskData.hTask == 0)
  1012. {
  1013. lError = SNMPAPI_NOT_INITIALIZED;
  1014. goto ERROR_OUT;
  1015. }
  1016. if (status != SNMPAPI_OFF) status = SNMPAPI_ON;
  1017. if (status == SNMPAPI_ON)
  1018. {
  1019. if (!snmpValidTableEntry(&SessDescr, nSes))
  1020. {
  1021. lError = SNMPAPI_SESSION_INVALID;
  1022. goto ERROR_OUT;
  1023. }
  1024. else // Got a valid session...save for possible error return
  1025. lSession = hSession;
  1026. }
  1027. if (hSrc)
  1028. {
  1029. nSrc = HandleToUlong(hSrc) - 1;
  1030. if (!snmpValidTableEntry(&EntsDescr, nSrc))
  1031. {
  1032. lError = SNMPAPI_ENTITY_INVALID;
  1033. goto ERROR_OUT;
  1034. }
  1035. pEntSrc = snmpGetTableEntry(&EntsDescr, nSrc);
  1036. }
  1037. if (hDst)
  1038. {
  1039. nDst = HandleToUlong(hDst) - 1;
  1040. if (!snmpValidTableEntry(&EntsDescr, nDst))
  1041. {
  1042. lError = SNMPAPI_ENTITY_INVALID;
  1043. goto ERROR_OUT;
  1044. }
  1045. pEntDst = snmpGetTableEntry(&EntsDescr, nDst);
  1046. }
  1047. if (hCtx)
  1048. {
  1049. nCtx = HandleToUlong(hCtx) - 1;
  1050. if (!snmpValidTableEntry(&CntxDescr, nCtx))
  1051. {
  1052. lError = SNMPAPI_CONTEXT_INVALID;
  1053. goto ERROR_OUT;
  1054. }
  1055. pCtxt = snmpGetTableEntry(&CntxDescr, nCtx);
  1056. }
  1057. if (notification)
  1058. {
  1059. if ((!notification->len) || notification->len > MAXOBJIDSIZE)
  1060. {
  1061. lError = SNMPAPI_SIZE_INVALID;
  1062. goto ERROR_OUT;
  1063. }
  1064. if (!notification->ptr)
  1065. {
  1066. lError = SNMPAPI_OID_INVALID;
  1067. goto ERROR_OUT;
  1068. }
  1069. }
  1070. EnterCriticalSection (&cs_TRAP);
  1071. for (nNotice = 0, nFound = 0; nNotice < TrapDescr.Allocated &&
  1072. nFound < TrapDescr.Used; nNotice++)
  1073. { // First, count now many we've tested
  1074. pTrap = snmpGetTableEntry(&TrapDescr, nNotice);
  1075. if (pTrap->Session) nFound++;
  1076. // then search for a parameter matches
  1077. if ((pTrap->Session == hSession) &&
  1078. (pTrap->ourEntity == hSrc) &&
  1079. (pTrap->agentEntity == hDst) &&
  1080. (pTrap->Context == hCtx))
  1081. { // Ok, we found one
  1082. if (!notification)
  1083. // if the notification parameter is null, then we
  1084. // want to either turn on or turn off all notifications
  1085. // from this match...so clear any entries already in
  1086. // the table and we'll add this wildcard entry if the
  1087. // operation is SNMPAPI_ON at the end.
  1088. {
  1089. DWORD dwUsed = TrapDescr.Used;
  1090. FreeRegister (nNotice);
  1091. if (dwUsed == TrapDescr.Used+1)
  1092. {
  1093. // Adjustment to nFound because FreeRegister has just decremented
  1094. // TrapDescr.Used by 1
  1095. nFound--;
  1096. }
  1097. continue;
  1098. }
  1099. else // notification specified
  1100. {
  1101. if (!pTrap->notification.len)
  1102. {
  1103. // Redundant request (already wildcarded)
  1104. // Skip it and return!
  1105. goto ERROR_PRECHECK;
  1106. }
  1107. else // pTrap->notification
  1108. {
  1109. // compare OIDs
  1110. SnmpOidCompare (notification, &(pTrap->notification),
  1111. 0, &nCmp);
  1112. if (nCmp) // no match
  1113. continue; // ...try the next one
  1114. else // !nCcmp
  1115. { // got a match...
  1116. // if SNMPAPI_ON, redundant request...skip it and return
  1117. // if SNMPAPI_OFF, free the entry first
  1118. if (status != SNMPAPI_ON)
  1119. FreeRegister (nNotice); // SNMPAPI_OFF
  1120. goto ERROR_PRECHECK;
  1121. } // end_else_!nCmp
  1122. } // end_else_TrapTable[nNotice].notificatin
  1123. } // end_else_notification_specified
  1124. } // end_if_we_found_one
  1125. } // end_for
  1126. if (status == SNMPAPI_OFF)
  1127. { // Found nothing to turn off...that's ok.
  1128. goto ERROR_PRECHECK;
  1129. }
  1130. //
  1131. // Special check for NT...is SNMPTRAP service running?
  1132. if (TaskData.trapThread == NULL &&
  1133. TaskData.sEnv.dwPlatformId == VER_PLATFORM_WIN32_NT)
  1134. {
  1135. DWORD dwReturn = SNMPAPI_TL_NOT_INITIALIZED;
  1136. DWORD pMode = PIPE_WAIT | PIPE_READMODE_MESSAGE;
  1137. LPCTSTR svcName = "SNMPTRAP";
  1138. LPCTSTR svcDesc = "SNMP Trap Service";
  1139. LPCTSTR svcPath = "%SystemRoot%\\system32\\snmptrap.exe";
  1140. SC_HANDLE scmHandle = NULL;
  1141. SC_HANDLE svcHandle = NULL;
  1142. SERVICE_STATUS svcStatus;
  1143. BOOL fStatus;
  1144. // Minimal SCM connection, for case when SNMPTRAP is running
  1145. scmHandle = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT);
  1146. if (scmHandle == NULL)
  1147. goto DONE_SC;
  1148. svcHandle = OpenService (scmHandle, svcName, SERVICE_QUERY_STATUS);
  1149. if (svcHandle == NULL)
  1150. {
  1151. if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
  1152. goto DONE_SC;
  1153. else
  1154. { // Must attempt to create service
  1155. PACL pAcl;
  1156. SECURITY_DESCRIPTOR S_Desc;
  1157. // Need new scmHandle with admin priv
  1158. CloseServiceHandle (scmHandle);
  1159. scmHandle = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
  1160. if (scmHandle == NULL)
  1161. goto DONE_SC; // Could not open SCM with admin priv
  1162. // Bug# 179644 The SNMP trap service should not run in the LocalSystem account
  1163. // We create the service with LocalService account instead of LocalSystem.
  1164. svcHandle = CreateService (scmHandle, svcName, svcDesc,
  1165. WRITE_DAC|SERVICE_QUERY_STATUS,
  1166. SERVICE_WIN32_OWN_PROCESS,
  1167. SERVICE_DEMAND_START,
  1168. SERVICE_ERROR_NORMAL,
  1169. svcPath,
  1170. NULL, NULL,
  1171. "TCPIP\0EventLog\0\0",
  1172. "NT AUTHORITY\\LocalService", NULL);
  1173. if (svcHandle == NULL)
  1174. goto DONE_SC; // Could not create service
  1175. if (!InitializeSecurityDescriptor (&S_Desc, SECURITY_DESCRIPTOR_REVISION))
  1176. {
  1177. goto DONE_SC;
  1178. }
  1179. if ((pAcl = AllocGenericACL()) == NULL ||
  1180. !SetSecurityDescriptorDacl (&S_Desc, TRUE, pAcl, FALSE))
  1181. {
  1182. FreeGenericACL(pAcl); // will free if necessary
  1183. goto DONE_SC;
  1184. }
  1185. if (!SetServiceObjectSecurity (svcHandle, DACL_SECURITY_INFORMATION, &S_Desc))
  1186. {
  1187. FreeGenericACL(pAcl);
  1188. goto DONE_SC;
  1189. }
  1190. FreeGenericACL(pAcl);
  1191. }
  1192. }
  1193. fStatus = QueryServiceStatus (svcHandle, &svcStatus);
  1194. while (fStatus)
  1195. {
  1196. switch (svcStatus.dwCurrentState)
  1197. {
  1198. case SERVICE_RUNNING:
  1199. dwReturn = SNMPAPI_SUCCESS;
  1200. goto DONE_SC;
  1201. case SERVICE_STOPPED:
  1202. // Start SNMPTRAP service if necessary
  1203. CloseServiceHandle (svcHandle);
  1204. svcHandle = OpenService (scmHandle, svcName, SERVICE_START|SERVICE_QUERY_STATUS);
  1205. if (svcHandle == NULL)
  1206. goto DONE_SC; // Could not start service
  1207. svcStatus.dwCurrentState = SERVICE_START_PENDING;
  1208. fStatus = StartService (svcHandle, 0, NULL);
  1209. break;
  1210. case SERVICE_STOP_PENDING:
  1211. case SERVICE_START_PENDING:
  1212. Sleep (MAX_PENDING_WAIT);
  1213. fStatus = QueryServiceStatus (svcHandle, &svcStatus);
  1214. break;
  1215. case SERVICE_PAUSED:
  1216. case SERVICE_PAUSE_PENDING:
  1217. case SERVICE_CONTINUE_PENDING:
  1218. default:
  1219. fStatus = FALSE; // Nothing to do about these
  1220. break;
  1221. }
  1222. }
  1223. DONE_SC:
  1224. if (scmHandle)
  1225. CloseServiceHandle (scmHandle);
  1226. if (svcHandle)
  1227. CloseServiceHandle (svcHandle);
  1228. if (dwReturn != SNMPAPI_SUCCESS)
  1229. {
  1230. ERROR_PRECHECK1:
  1231. lError = dwReturn;
  1232. goto ERROR_PRECHECK;
  1233. }
  1234. // Setup for pipe-oriented operations
  1235. dwReturn = SNMPAPI_TL_RESOURCE_ERROR;
  1236. // block on instance of server pipe becoming available
  1237. if (!WaitNamedPipe (SNMPTRAPPIPE, TRAPSERVERTIMEOUT))
  1238. goto ERROR_PRECHECK1;
  1239. TaskData.trapPipe =
  1240. // Bug# 270672 Change FILE_ATTRIBUTE_NORMAL to FILE_FLAG_OVERLAPPED
  1241. CreateFile (SNMPTRAPPIPE, GENERIC_READ|GENERIC_WRITE,
  1242. FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
  1243. OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
  1244. if (TaskData.trapPipe == INVALID_HANDLE_VALUE)
  1245. goto ERROR_PRECHECK1;
  1246. if (!SetNamedPipeHandleState (TaskData.trapPipe, &pMode, NULL, NULL))
  1247. {
  1248. CloseHandle (TaskData.trapPipe);
  1249. TaskData.trapPipe = INVALID_HANDLE_VALUE;
  1250. goto ERROR_PRECHECK1;
  1251. }
  1252. } // end_NT check for SNMPTRAP service
  1253. //If we got this far, add it
  1254. lError = snmpAllocTableEntry(&TrapDescr, &nNotice);
  1255. if (lError != SNMPAPI_SUCCESS)
  1256. goto ERROR_PRECHECK;
  1257. pTrap = snmpGetTableEntry(&TrapDescr, nNotice);
  1258. // add it
  1259. pTrap->Session = hSession;
  1260. // Deliberate assignments in next three if statements
  1261. if (pTrap->ourEntity = hSrc)
  1262. //EntityTable[nSrc-1].refCount++; -- was this a bug??? nSrc is already 0 based
  1263. pEntSrc->refCount++;
  1264. if (pTrap->agentEntity = hDst)
  1265. //EntityTable[nDst-1].refCount++; -- was this a bug??? nDst is already 0 based
  1266. pEntDst->refCount++;
  1267. if (pTrap->Context = hCtx)
  1268. //ContextTable[nCtx-1].refCount++; -- was this a bug?? nCtx is already 0 based
  1269. pCtxt->refCount++;
  1270. if (notification)
  1271. { // Reproduce the OID
  1272. pTrap->notification.ptr = NULL;
  1273. // Deliberate assignment in next statement
  1274. if (pTrap->notification.len = notification->len)
  1275. {
  1276. if (pTrap->notification.len > MAXTRAPIDS)
  1277. pTrap->notification.len = MAXTRAPIDS;
  1278. if (notification->ptr)
  1279. {
  1280. // Deliberate assignment in next statement
  1281. pTrap->notification.ptr = &(pTrap->notificationValue[0]);
  1282. CopyMemory (pTrap->notification.ptr, notification->ptr,
  1283. pTrap->notification.len * sizeof(smiUINT32));
  1284. }
  1285. }
  1286. }
  1287. if (TaskData.trapThread == NULL)
  1288. {
  1289. DWORD thrId;
  1290. TaskData.trapThread = (HANDLE)_beginthreadex (NULL, 0, thrTrap, NULL, 0, &thrId);
  1291. if (TaskData.trapThread == NULL)
  1292. {
  1293. FreeRegister(nNotice);
  1294. lError = SNMPAPI_TL_RESOURCE_ERROR;
  1295. }
  1296. }
  1297. ERROR_PRECHECK:
  1298. LeaveCriticalSection (&cs_TRAP);
  1299. if (lError == SNMPAPI_SUCCESS)
  1300. return (SNMPAPI_SUCCESS);
  1301. ERROR_OUT:
  1302. return (SaveError (lSession, lError));
  1303. } // end_SnmpRegister
  1304. void FreeMsg (DWORD nMsg)
  1305. {
  1306. LPSNMPMSG pMsg;
  1307. EnterCriticalSection (&cs_MSG);
  1308. // Decrement reference counts
  1309. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  1310. SnmpFreeEntity (pMsg->agentEntity);
  1311. SnmpFreeEntity (pMsg->ourEntity);
  1312. SnmpFreeContext (pMsg->Context);
  1313. if (pMsg->Addr)
  1314. GlobalFree (pMsg->Addr);
  1315. snmpFreeTableEntry(&MsgDescr, nMsg);
  1316. LeaveCriticalSection (&cs_MSG);
  1317. return;
  1318. } // end_FreeMsg
  1319. SNMPAPI_STATUS SNMPAPI_CALL
  1320. SnmpListen (IN HSNMP_ENTITY hEntity,
  1321. IN smiUINT32 status)
  1322. {
  1323. smiUINT32 nAgent = 0;
  1324. DWORD thrId;
  1325. DWORD nEntity = HandleToUlong(hEntity) - 1;
  1326. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  1327. HSNMP_SESSION lSession = 0;
  1328. LPENTITY pEntity;
  1329. LPAGENT pAgent;
  1330. if (TaskData.hTask == 0)
  1331. {
  1332. lError = SNMPAPI_NOT_INITIALIZED;
  1333. goto ERROR_OUT;
  1334. }
  1335. if (!snmpValidTableEntry(&EntsDescr, nEntity))
  1336. {
  1337. lError = SNMPAPI_ENTITY_INVALID;
  1338. goto ERROR_OUT;
  1339. }
  1340. pEntity = snmpGetTableEntry(&EntsDescr, nEntity);
  1341. lSession = pEntity->Session;
  1342. if (status != SNMPAPI_ON && status != SNMPAPI_OFF)
  1343. {
  1344. lError = SNMPAPI_MODE_INVALID;
  1345. goto ERROR_OUT;
  1346. }
  1347. EnterCriticalSection (&cs_ENTITY);
  1348. EnterCriticalSection (&cs_AGENT);
  1349. if (status)
  1350. { // status == SNMPAPI_ON
  1351. int nProto = IPPROTO_UDP;
  1352. int nSize = sizeof(SOCKADDR_IN);
  1353. int nFamily = pEntity->addr.inet.sin_family;
  1354. if (pEntity->Agent)
  1355. { // Entity already running as agent
  1356. lError = SNMPAPI_NOOP;
  1357. goto ERROR_PRECHECK;
  1358. }
  1359. // Allocate a slot in AGENT table
  1360. lError = snmpAllocTableEntry(&AgentDescr, &nAgent);
  1361. if (lError != SNMPAPI_SUCCESS)
  1362. goto ERROR_PRECHECK;
  1363. pAgent = snmpGetTableEntry(&AgentDescr, nAgent);
  1364. // Agent table entry allocated...setup for agent thread
  1365. if (nFamily == AF_IPX)
  1366. {
  1367. nProto = NSPROTO_IPX;
  1368. nSize = sizeof(SOCKADDR_IPX);
  1369. }
  1370. pAgent->Socket = socket (nFamily, SOCK_DGRAM, nProto);
  1371. if (pAgent->Socket == INVALID_SOCKET)
  1372. {
  1373. snmpFreeTableEntry(&AgentDescr, nAgent);
  1374. lError = SNMPAPI_TL_RESOURCE_ERROR;
  1375. goto ERROR_PRECHECK;
  1376. }
  1377. if (bind (pAgent->Socket,
  1378. (LPSOCKADDR)&pEntity->addr, nSize)
  1379. == SOCKET_ERROR)
  1380. {
  1381. closesocket (pAgent->Socket);
  1382. snmpFreeTableEntry(&AgentDescr, nAgent);
  1383. lError = SNMPAPI_TL_OTHER;
  1384. goto ERROR_PRECHECK;
  1385. }
  1386. // Make Entity and Agent point to each other
  1387. pEntity->Agent = nAgent + 1;
  1388. pAgent->Entity = hEntity;
  1389. pAgent->Session = lSession;
  1390. // Create agent thread...needs error checking
  1391. pAgent->Thread = (HANDLE)_beginthreadex (NULL, 0, thrAgent, (LPVOID) ULongToPtr(nAgent), 0, &thrId);
  1392. if (pAgent->Thread == NULL)
  1393. {
  1394. closesocket(pAgent->Socket);
  1395. snmpFreeTableEntry(&AgentDescr, nAgent);
  1396. lError = SNMPAPI_TL_RESOURCE_ERROR;
  1397. goto ERROR_PRECHECK;
  1398. }
  1399. } // end_if status == SNMPAPI_ON
  1400. else
  1401. { // status == SNMPAPI_OFF
  1402. if (!pEntity->Agent)
  1403. { // Entity not running as agent
  1404. lError = SNMPAPI_NOOP;
  1405. goto ERROR_PRECHECK;
  1406. }
  1407. // Entity is running as agent
  1408. nAgent = pEntity->Agent - 1;
  1409. pAgent = snmpGetTableEntry(&AgentDescr, nAgent);
  1410. closesocket (pAgent->Socket);
  1411. WaitForSingleObject (pAgent->Thread, INFINITE);
  1412. CloseHandle (pAgent->Thread);
  1413. snmpFreeTableEntry(&AgentDescr, nAgent);
  1414. // Must terminate entity's agent status
  1415. pEntity->Agent = 0;
  1416. // Must terminate entity if nothing else was using it
  1417. if (pEntity->refCount == 0)
  1418. SnmpFreeEntity (hEntity);
  1419. } // end_else status == SNMPAPI_OFF
  1420. ERROR_PRECHECK:
  1421. LeaveCriticalSection (&cs_AGENT);
  1422. LeaveCriticalSection (&cs_ENTITY);
  1423. ERROR_OUT:
  1424. if (lError == SNMPAPI_SUCCESS)
  1425. return (SNMPAPI_SUCCESS);
  1426. else
  1427. return (SaveError (lSession, lError));
  1428. } // end_SnmpListen()
  1429. SNMPAPI_STATUS SNMPAPI_CALL
  1430. SnmpCancelMsg (HSNMP_SESSION hSession, smiINT32 nReqID)
  1431. {
  1432. DWORD nMsg = 0;
  1433. DWORD nFound = 0;
  1434. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  1435. HSNMP_SESSION lSession = 0;
  1436. LPSNMPMSG pMsg;
  1437. if (TaskData.hTask == 0)
  1438. {
  1439. lError = SNMPAPI_NOT_INITIALIZED;
  1440. goto ERROR_OUT;
  1441. }
  1442. if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1))
  1443. {
  1444. lError = SNMPAPI_SESSION_INVALID;
  1445. goto ERROR_OUT;
  1446. }
  1447. lSession = hSession;
  1448. EnterCriticalSection (&cs_MSG);
  1449. while (nFound < MsgDescr.Used && nMsg < MsgDescr.Allocated)
  1450. {
  1451. pMsg = snmpGetTableEntry(&MsgDescr, nMsg);
  1452. // Deliberate assignement in next conditional
  1453. if (pMsg->Session)
  1454. {
  1455. nFound++;
  1456. if (pMsg->Session == hSession)
  1457. {
  1458. if (pMsg->Status == NP_SENT &&
  1459. pMsg->appReqId == (smiUINT32)nReqID)
  1460. {
  1461. FreeMsg (nMsg);
  1462. goto ERROR_PRECHECK;
  1463. }
  1464. }
  1465. }
  1466. nMsg++;
  1467. }
  1468. // Falied to find a MSG that matched the request
  1469. lError = SNMPAPI_PDU_INVALID;
  1470. ERROR_PRECHECK:
  1471. LeaveCriticalSection (&cs_MSG);
  1472. if (lError == SNMPAPI_SUCCESS)
  1473. return (SNMPAPI_SUCCESS);
  1474. // else...failure case
  1475. ERROR_OUT:
  1476. return (SaveError (lSession, lError));
  1477. } // end_SnmpCancelMsg