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.

3882 lines
94 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. mgmtapi.c
  5. Abstract:
  6. SNMP Management API (wrapped around WinSNMP API).
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 05-Feb-1997 DonRyan
  11. Rewrote functions to be wrappers around WinSNMP.
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include Files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <windows.h>
  22. #include <wsipx.h>
  23. #include <winsnmp.h>
  24. #include <mgmtapi.h>
  25. #include <oidconv.h>
  26. #include <snmputil.h>
  27. ///////////////////////////////////////////////////////////////////////////////
  28. // //
  29. // Private Definitions //
  30. // //
  31. ///////////////////////////////////////////////////////////////////////////////
  32. typedef struct _SNMP_MGR_SESSION {
  33. SOCKET UnusedSocket; // WARNING: Previous versions of the
  34. struct sockaddr UnusedDestAddr; // MGMTAPI.H header file exposed the
  35. LPSTR UnusedCommunity; // SNMP_MGR_SESSION structure which
  36. INT UnusedTimeout; // unfortunately encouraged people to
  37. INT UnusedNumRetries; // muck with it. Since this structure
  38. AsnInteger UnusedRequestId; // has now changed we must protect it.
  39. CRITICAL_SECTION SessionLock; // multiple threads may share session
  40. HSNMP_SESSION hSnmpSession; // handle to winsnmp session
  41. HSNMP_ENTITY hAgentEntity; // handle to agent entity
  42. HSNMP_ENTITY hManagerEntity; // handle to manager entity
  43. HSNMP_CONTEXT hViewContext; // handle to view context
  44. HSNMP_PDU hPdu; // handle to snmp pdu
  45. HSNMP_VBL hVbl; // handle to snmp pdu
  46. HWND hWnd; // handle to window
  47. smiINT32 nPduType; // current pdu type
  48. smiINT32 nRequestId; // current request id
  49. smiINT32 nErrorIndex; // error index from pdu
  50. smiINT32 nErrorStatus; // error status from pdu
  51. smiINT32 nLastError; // last system error
  52. SnmpVarBindList * pVarBindList; // pointer to varbind list
  53. } SNMP_MGR_SESSION, *PSNMP_MGR_SESSION;
  54. typedef struct _TRAP_LIST_ENTRY {
  55. LIST_ENTRY Link; // linked-list link
  56. AsnObjectIdentifier EnterpriseOID; // generating enterprise
  57. AsnNetworkAddress AgentAddress; // generating agent addr
  58. AsnNetworkAddress SourceAddress; // generating network addr
  59. AsnInteger nGenericTrap; // generic trap type
  60. AsnInteger nSpecificTrap; // enterprise specific type
  61. AsnOctetString Community; // generating community
  62. AsnTimeticks TimeStamp; // time stamp
  63. SnmpVarBindList VarBindList; // variable bindings
  64. } TRAP_LIST_ENTRY, * PTRAP_LIST_ENTRY;
  65. #define IPADDRLEN 4
  66. #define IPXADDRLEN 10
  67. #define MAXENTITYSTRLEN 128
  68. #define MINVARBINDLEN 2
  69. #define SYSUPTIMEINDEX 0
  70. #define SNMPTRAPOIDINDEX 1
  71. #define DEFAULT_ADDRESS_IP "127.0.0.1"
  72. #define DEFAULT_ADDRESS_IPX "00000000.000000000000"
  73. #define NOTIFICATION_CLASS "MGMTAPI Notification Class"
  74. #define WM_WSNMP_INCOMING (WM_USER + 1)
  75. #define WM_WSNMP_DONE (WM_USER + 2)
  76. #define WSNMP_FAILED(s) ((s) == SNMPAPI_FAILURE)
  77. #define WSNMP_SUCCEEDED(s) ((s) != SNMPAPI_FAILURE)
  78. #define WSNMP_ASSERT(s) ASSERT((s))
  79. ///////////////////////////////////////////////////////////////////////////////
  80. // //
  81. // Global Variables //
  82. // //
  83. ///////////////////////////////////////////////////////////////////////////////
  84. HINSTANCE g_hDll; // module handle
  85. HANDLE g_hTrapEvent = NULL; // trap event handle
  86. HANDLE g_hTrapThread = NULL; // trap thread handle
  87. HANDLE g_hTrapRegisterdEvent = NULL; // event to sync. SnmpMgrTrapListen
  88. BOOL g_fIsSnmpStarted = FALSE; // indicates winsnmp inited
  89. BOOL g_fIsSnmpListening = FALSE; // indicates trap thread on
  90. BOOL g_fIsTrapRegistered = FALSE; // indicates trap registered
  91. DWORD g_dwRequestId = 1; // unique pdu request id
  92. LIST_ENTRY g_IncomingTraps; // incoming trap queue
  93. CRITICAL_SECTION g_GlobalLock; // process resource lock
  94. SNMP_MGR_SESSION g_TrapSMS; // process trap session
  95. DWORD g_cSnmpMgmtRef = 0; // ref. count on using mgmtapi
  96. ///////////////////////////////////////////////////////////////////////////////
  97. // //
  98. // Private Procedures //
  99. // //
  100. ///////////////////////////////////////////////////////////////////////////////
  101. DWORD
  102. GetRequestId(
  103. )
  104. /*++
  105. Routine Description:
  106. Retrieve next global request id.
  107. Arguments:
  108. None.
  109. Return Values:
  110. Returns request id.
  111. --*/
  112. {
  113. DWORD dwRequestId;
  114. // obtain exclusive access to request id
  115. EnterCriticalSection(&g_GlobalLock);
  116. // obtain copy of request id
  117. dwRequestId = g_dwRequestId++;
  118. // obtain exclusive access to request id
  119. LeaveCriticalSection(&g_GlobalLock);
  120. return dwRequestId;
  121. }
  122. BOOL
  123. TransferVb(
  124. PSNMP_MGR_SESSION pSMS,
  125. SnmpVarBind * pVarBind
  126. )
  127. /*++
  128. Routine Description:
  129. Transfer VarBind structure to WinSNMP structure.
  130. Arguments:
  131. pSMS - pointer to mgmtapi session structure.
  132. pVarBind - pointer to varbind to transfer.
  133. Return Values:
  134. Returns true if successful.
  135. --*/
  136. {
  137. BOOL fOk = FALSE;
  138. SNMPAPI_STATUS status;
  139. smiVALUE tmpValue;
  140. smiOID tmpOID;
  141. // validate session ptr
  142. WSNMP_ASSERT(pSMS != NULL);
  143. // validate pointers
  144. if ((pVarBind != NULL) &&
  145. (pVarBind->name.ids != NULL) &&
  146. (pVarBind->name.idLength != 0)) {
  147. // re-init
  148. fOk = TRUE;
  149. // transfer oid information
  150. tmpOID.len = pVarBind->name.idLength;
  151. tmpOID.ptr = pVarBind->name.ids;
  152. // only initialize value if set
  153. if (pSMS->nPduType == SNMP_PDU_SET) {
  154. // syntax values are equivalent
  155. tmpValue.syntax = (smiINT32)(BYTE)pVarBind->value.asnType;
  156. // determine type
  157. switch (pVarBind->value.asnType) {
  158. case ASN_INTEGER32:
  159. // transfer signed int
  160. tmpValue.value.sNumber = pVarBind->value.asnValue.number;
  161. break;
  162. case ASN_UNSIGNED32:
  163. case ASN_COUNTER32:
  164. case ASN_GAUGE32:
  165. case ASN_TIMETICKS:
  166. // transfer unsigned int
  167. tmpValue.value.uNumber = pVarBind->value.asnValue.unsigned32;
  168. break;
  169. case ASN_COUNTER64:
  170. // transfer 64-bit counter
  171. tmpValue.value.hNumber.lopart =
  172. pVarBind->value.asnValue.counter64.LowPart;
  173. tmpValue.value.hNumber.hipart =
  174. pVarBind->value.asnValue.counter64.HighPart;
  175. break;
  176. case ASN_OPAQUE:
  177. case ASN_IPADDRESS:
  178. case ASN_OCTETSTRING:
  179. case ASN_BITS:
  180. // transfer octet string
  181. tmpValue.value.string.len =
  182. pVarBind->value.asnValue.string.length;
  183. tmpValue.value.string.ptr =
  184. pVarBind->value.asnValue.string.stream;
  185. break;
  186. case ASN_OBJECTIDENTIFIER:
  187. // transfer object id
  188. tmpValue.value.oid.len =
  189. pVarBind->value.asnValue.object.idLength;
  190. tmpValue.value.oid.ptr =
  191. pVarBind->value.asnValue.object.ids;
  192. break;
  193. case ASN_NULL:
  194. case SNMP_EXCEPTION_NOSUCHOBJECT:
  195. case SNMP_EXCEPTION_NOSUCHINSTANCE:
  196. case SNMP_EXCEPTION_ENDOFMIBVIEW:
  197. // initialize empty byte
  198. tmpValue.value.empty = 0;
  199. break;
  200. default:
  201. // failure
  202. fOk = FALSE;
  203. break;
  204. }
  205. }
  206. if (fOk) {
  207. // register varbind
  208. status = SnmpSetVb(
  209. pSMS->hVbl,
  210. 0, // index
  211. &tmpOID,
  212. (pSMS->nPduType == SNMP_PDU_SET)
  213. ? &tmpValue
  214. : NULL
  215. );
  216. // validate return code
  217. if (WSNMP_FAILED(status)) {
  218. SNMPDBG((
  219. SNMP_LOG_ERROR,
  220. "MGMTAPI: SnmpSetVb returned %d.\n",
  221. SnmpGetLastError(pSMS->hSnmpSession)
  222. ));
  223. // failure
  224. fOk = FALSE;
  225. }
  226. }
  227. }
  228. return fOk;
  229. }
  230. BOOL
  231. AllocateVbl(
  232. PSNMP_MGR_SESSION pSMS
  233. )
  234. /*++
  235. Routine Description:
  236. Transfer VarBindList structure to WinSNMP structure.
  237. Arguments:
  238. pSMS - pointer to mgmtapi session structure.
  239. Return Values:
  240. Returns true if successful.
  241. --*/
  242. {
  243. BOOL fOk = FALSE;
  244. SNMPAPI_STATUS status;
  245. SnmpVarBind * pVarBind;
  246. DWORD cVarBind;
  247. // validate session ptr
  248. WSNMP_ASSERT(pSMS != NULL);
  249. // validate parameters
  250. WSNMP_ASSERT(pSMS->pVarBindList != NULL);
  251. WSNMP_ASSERT(pSMS->pVarBindList->len != 0);
  252. WSNMP_ASSERT(pSMS->pVarBindList->list != NULL);
  253. // allocate resources for variable bindings list
  254. pSMS->hVbl = SnmpCreateVbl(pSMS->hSnmpSession, NULL, NULL);
  255. // validate varbind handle
  256. if (WSNMP_SUCCEEDED(pSMS->hVbl)) {
  257. // re-init
  258. fOk = TRUE;
  259. // initialize varbind pointer
  260. pVarBind = pSMS->pVarBindList->list;
  261. // initialize varbind count
  262. cVarBind = pSMS->pVarBindList->len;
  263. // process each varbind
  264. while (fOk && cVarBind--) {
  265. // transfer variable binding
  266. fOk = TransferVb(pSMS, pVarBind++);
  267. }
  268. if (!fOk) {
  269. // release varbind list handle
  270. status = SnmpFreeVbl(pSMS->hVbl);
  271. // validate return code
  272. if (WSNMP_FAILED(status)) {
  273. SNMPDBG((
  274. SNMP_LOG_ERROR,
  275. "MGMTAPI: SnmpFreeVbl returned %d.\n",
  276. SnmpGetLastError(pSMS->hSnmpSession)
  277. ));
  278. }
  279. // re-initialize
  280. pSMS->hVbl = (HSNMP_VBL)NULL;
  281. }
  282. } else {
  283. SNMPDBG((
  284. SNMP_LOG_ERROR,
  285. "MGMTAPI: SnmpCreateVbl returned %d.\n",
  286. SnmpGetLastError(pSMS->hSnmpSession)
  287. ));
  288. }
  289. return fOk;
  290. }
  291. BOOL
  292. FreeVbl(
  293. PSNMP_MGR_SESSION pSMS
  294. )
  295. /*++
  296. Routine Description:
  297. Cleanup VarBind resources from WinSNMP structure.
  298. Arguments:
  299. pSMS - pointer to mgmtapi session structure.
  300. Return Values:
  301. Returns true if successful.
  302. --*/
  303. {
  304. BOOL fOk = TRUE;
  305. SNMPAPI_STATUS status;
  306. // validate session ptr
  307. WSNMP_ASSERT(pSMS != NULL);
  308. // validate handle
  309. if (pSMS->hVbl != (HSNMP_VBL)NULL) {
  310. // actually release vbl handle
  311. status = SnmpFreeVbl(pSMS->hVbl);
  312. // validate return code
  313. if (WSNMP_FAILED(status)) {
  314. SNMPDBG((
  315. SNMP_LOG_ERROR,
  316. "MGMTAPI: SnmpFreeVbl returned %d.\n",
  317. SnmpGetLastError(pSMS->hSnmpSession)
  318. ));
  319. // failure
  320. fOk = FALSE;
  321. }
  322. // re-initialize handle
  323. pSMS->hVbl = (HSNMP_VBL)NULL;
  324. }
  325. return fOk;
  326. }
  327. BOOL
  328. AllocatePdu(
  329. PSNMP_MGR_SESSION pSMS
  330. )
  331. /*++
  332. Routine Description:
  333. Initialize session structure for sending request.
  334. Arguments:
  335. pSMS - pointer to mgmtapi session structure.
  336. Return Values:
  337. Returns true if successful.
  338. --*/
  339. {
  340. BOOL fOk = FALSE;
  341. // validate session ptr
  342. WSNMP_ASSERT(pSMS != NULL);
  343. // transfer varbinds
  344. if (AllocateVbl(pSMS)) {
  345. // grab next shared request id
  346. pSMS->nRequestId = GetRequestId();
  347. // create request pdu
  348. pSMS->hPdu = SnmpCreatePdu(
  349. pSMS->hSnmpSession,
  350. pSMS->nPduType,
  351. pSMS->nRequestId,
  352. 0, // errorStatus
  353. 0, // errorIndex
  354. pSMS->hVbl
  355. );
  356. // validate return status
  357. if (WSNMP_SUCCEEDED(pSMS->hPdu)) {
  358. // success
  359. fOk = TRUE;
  360. } else {
  361. SNMPDBG((
  362. SNMP_LOG_ERROR,
  363. "MGMTAPI: SnmpCreatePdu returned %d.\n",
  364. SnmpGetLastError(pSMS->hSnmpSession)
  365. ));
  366. // free resources
  367. FreeVbl(pSMS);
  368. }
  369. }
  370. return fOk;
  371. }
  372. BOOL
  373. FreePdu(
  374. PSNMP_MGR_SESSION pSMS
  375. )
  376. /*++
  377. Routine Description:
  378. Cleanup session structure after processing response.
  379. Arguments:
  380. pSMS - pointer to mgmtapi session structure.
  381. Return Values:
  382. Returns true if successful.
  383. --*/
  384. {
  385. BOOL fOk = TRUE;
  386. SNMPAPI_STATUS status;
  387. // validate session ptr
  388. WSNMP_ASSERT(pSMS != NULL);
  389. // validate handle
  390. if (pSMS->hPdu != (HSNMP_PDU)NULL) {
  391. // free vbl
  392. FreeVbl(pSMS);
  393. // actually release pdu handle
  394. status = SnmpFreePdu(pSMS->hPdu);
  395. // validate return code
  396. if (WSNMP_FAILED(status)) {
  397. SNMPDBG((
  398. SNMP_LOG_ERROR,
  399. "MGMTAPI: SnmpFreePdu returned %d.\n",
  400. SnmpGetLastError(pSMS->hSnmpSession)
  401. ));
  402. // failure
  403. fOk = FALSE;
  404. }
  405. // re-initialize handle
  406. pSMS->hPdu = (HSNMP_PDU)NULL;
  407. }
  408. return fOk;
  409. }
  410. BOOL
  411. CopyOid(
  412. AsnObjectIdentifier * pDstOID,
  413. smiLPOID pSrcOID
  414. )
  415. /*++
  416. Routine Description:
  417. Copies object identifier from WinSNMP format to MGMTAPI format.
  418. Arguments:
  419. pDstOID - points to MGMTAPI structure to receive OID.
  420. pSrcOID - points to WinSNMP structure to copy.
  421. Return Values:
  422. Returns true if successful.
  423. Note: if pSrcOID is valid, its contents will be freed regardless of
  424. return value
  425. --*/
  426. {
  427. BOOL fOk = FALSE;
  428. // validate pointers
  429. WSNMP_ASSERT(pDstOID != NULL);
  430. WSNMP_ASSERT(pSrcOID != NULL);
  431. WSNMP_ASSERT(pSrcOID->len != 0);
  432. WSNMP_ASSERT(pSrcOID->ptr != NULL);
  433. // store the number of subids
  434. pDstOID->idLength = pSrcOID->len;
  435. // allocate memory for subidentifiers
  436. pDstOID->ids = SnmpUtilMemAlloc(pDstOID->idLength * sizeof(DWORD));
  437. // validate pointer
  438. if (pDstOID->ids != NULL) {
  439. // transfer memory
  440. memcpy(pDstOID->ids,
  441. pSrcOID->ptr,
  442. pDstOID->idLength * sizeof(DWORD)
  443. );
  444. // success
  445. fOk = TRUE;
  446. }
  447. // now release memory for original oid
  448. SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE)pSrcOID);
  449. return fOk;
  450. }
  451. BOOL
  452. CopyOctets(
  453. AsnOctetString * pDstOctets,
  454. smiLPOCTETS pSrcOctets
  455. )
  456. /*++
  457. Routine Description:
  458. Copies octet string from WinSNMP format to MGMTAPI format.
  459. Arguments:
  460. pDstOctets - points to MGMTAPI structure to receive octets.
  461. pSrcOctets - points to WinSNMP structure to copy.
  462. Return Values:
  463. Returns true if successful.
  464. Note: if pSrcOctets is valid, its contents will be freed regardless of
  465. return value
  466. --*/
  467. {
  468. BOOL fOk = FALSE;
  469. SNMPAPI_STATUS status;
  470. // validate pointers
  471. WSNMP_ASSERT(pDstOctets != NULL);
  472. WSNMP_ASSERT(pSrcOctets != NULL);
  473. // it is legitimate that
  474. // 1. pSrcOctets->len == 0
  475. // 2. pSrcOctets->ptr == NULL
  476. if (pSrcOctets->len == 0 || pSrcOctets->ptr == NULL)
  477. {
  478. pDstOctets->dynamic = FALSE;
  479. pDstOctets->length = 0;
  480. pDstOctets->stream = NULL;
  481. fOk = TRUE;
  482. }
  483. else
  484. {
  485. // allocate memory for octet string
  486. pDstOctets->stream = SnmpUtilMemAlloc(pSrcOctets->len);
  487. // validate pointer
  488. if (pDstOctets->stream != NULL) {
  489. // octet string allocated
  490. pDstOctets->dynamic = TRUE;
  491. // store the number of bytes
  492. pDstOctets->length = pSrcOctets->len;
  493. // transfer memory
  494. memcpy(pDstOctets->stream,
  495. pSrcOctets->ptr,
  496. pDstOctets->length
  497. );
  498. // success
  499. fOk = TRUE;
  500. }
  501. }
  502. // now release memory for original string
  503. SnmpFreeDescriptor(SNMP_SYNTAX_OCTETS, (smiLPOPAQUE)pSrcOctets);
  504. return fOk;
  505. }
  506. CopyVb(
  507. PSNMP_MGR_SESSION pSMS,
  508. DWORD iVarBind,
  509. SnmpVarBind * pVarBind
  510. )
  511. /*++
  512. Routine Description:
  513. Copy variable binding from WinSNMP structure to MGMTAPI structure.
  514. Arguments:
  515. pSMS - pointer to mgmtapi session structure.
  516. iVarBind - index of varbind structure to copy.
  517. pVarBind - pointer to varbind structure.
  518. Return Values:
  519. Returns true if successful.
  520. --*/
  521. {
  522. BOOL fOk = FALSE;
  523. SNMPAPI_STATUS status;
  524. smiOID tmpOID;
  525. smiVALUE tmpValue;
  526. // validate session ptr
  527. WSNMP_ASSERT(pSMS != NULL);
  528. WSNMP_ASSERT(pVarBind != NULL);
  529. // attempt to retrieve varbind data from winsnmp structure
  530. status = SnmpGetVb(pSMS->hVbl, iVarBind, &tmpOID, &tmpValue);
  531. // validate return code
  532. if (WSNMP_SUCCEEDED(status)) {
  533. // transfer object identifier value
  534. fOk = CopyOid(&pVarBind->name, &tmpOID);
  535. // syntax values are equivalent
  536. pVarBind->value.asnType = (BYTE)(smiINT32)tmpValue.syntax;
  537. // determine syntax
  538. switch (tmpValue.syntax) {
  539. case SNMP_SYNTAX_INT32:
  540. // transfer signed int
  541. pVarBind->value.asnValue.number = tmpValue.value.sNumber;
  542. break;
  543. case SNMP_SYNTAX_UINT32:
  544. case SNMP_SYNTAX_CNTR32:
  545. case SNMP_SYNTAX_GAUGE32:
  546. case SNMP_SYNTAX_TIMETICKS:
  547. // transfer unsigned int
  548. pVarBind->value.asnValue.unsigned32 = tmpValue.value.uNumber;
  549. break;
  550. case SNMP_SYNTAX_CNTR64:
  551. // transfer 64-bit counter
  552. pVarBind->value.asnValue.counter64.LowPart =
  553. tmpValue.value.hNumber.lopart;
  554. pVarBind->value.asnValue.counter64.HighPart =
  555. tmpValue.value.hNumber.hipart;
  556. break;
  557. case SNMP_SYNTAX_OPAQUE:
  558. case SNMP_SYNTAX_IPADDR:
  559. case SNMP_SYNTAX_OCTETS:
  560. case SNMP_SYNTAX_BITS:
  561. // transfer octet string
  562. if (!CopyOctets(&pVarBind->value.asnValue.string,
  563. &tmpValue.value.string)) {
  564. // re-initialize
  565. pVarBind->value.asnType = ASN_NULL;
  566. // failure
  567. fOk = FALSE;
  568. }
  569. break;
  570. case SNMP_SYNTAX_OID:
  571. // transfer object identifier
  572. if (!CopyOid(&pVarBind->value.asnValue.object,
  573. &tmpValue.value.oid)) {
  574. // re-initialize
  575. pVarBind->value.asnType = ASN_NULL;
  576. // failure
  577. fOk = FALSE;
  578. }
  579. break;
  580. case SNMP_SYNTAX_NULL:
  581. case SNMP_SYNTAX_NOSUCHOBJECT:
  582. case SNMP_SYNTAX_NOSUCHINSTANCE:
  583. case SNMP_SYNTAX_ENDOFMIBVIEW:
  584. break; // do nothing...
  585. default:
  586. SNMPDBG((
  587. SNMP_LOG_ERROR,
  588. "MGMTAPI: SnmpGetVb returned invalid type.\n"
  589. ));
  590. // re-initialize
  591. pVarBind->value.asnType = ASN_NULL;
  592. // failure
  593. fOk = FALSE;
  594. break;
  595. }
  596. } else {
  597. SNMPDBG((
  598. SNMP_LOG_ERROR,
  599. "MGMTAPI: SnmpGetVb returned %d.\n",
  600. SnmpGetLastError(pSMS->hSnmpSession)
  601. ));
  602. }
  603. return fOk;
  604. }
  605. BOOL
  606. CopyVbl(
  607. PSNMP_MGR_SESSION pSMS,
  608. SnmpVarBindList * pVarBindList
  609. )
  610. /*++
  611. Routine Description:
  612. Copy variable bindings from WinSNMP structure to MGMTAPI structure.
  613. Arguments:
  614. pSMS - pointer to mgmtapi session structure.
  615. pVarBindList - pointer to varbind list structure.
  616. Return Values:
  617. Returns true if successful.
  618. --*/
  619. {
  620. BOOL fOk = TRUE;
  621. // validate session ptr
  622. WSNMP_ASSERT(pSMS != NULL);
  623. WSNMP_ASSERT(pVarBindList != NULL);
  624. // initialize
  625. pVarBindList->len = 0;
  626. pVarBindList->list = NULL;
  627. // validate varbind list handle
  628. if (pSMS->hVbl != (HSNMP_VBL)NULL) {
  629. // determine number of varbinds
  630. pVarBindList->len = SnmpCountVbl(pSMS->hVbl);
  631. // validate number of varbinds
  632. if (WSNMP_SUCCEEDED(pVarBindList->len)) {
  633. // allocate memory for varbinds
  634. pVarBindList->list = SnmpUtilMemAlloc(
  635. pVarBindList->len *
  636. sizeof(SnmpVarBind)
  637. );
  638. // validate pointer
  639. if (pVarBindList->list != NULL) {
  640. DWORD cVarBind = 1;
  641. SnmpVarBind * pVarBind;
  642. // save pointer to varbinds
  643. pVarBind = pVarBindList->list;
  644. // process varbinds in the list
  645. while (fOk && (cVarBind <= pVarBindList->len)) {
  646. // copy varbind from winsnmp to mgmtapi
  647. fOk = CopyVb(pSMS, cVarBind++, pVarBind++);
  648. }
  649. } else {
  650. SNMPDBG((
  651. SNMP_LOG_ERROR,
  652. "MGMTAPI: Could not allocate VBL.\n"
  653. ));
  654. // re-initialize
  655. pVarBindList->len = 0;
  656. // failure
  657. fOk = FALSE;
  658. }
  659. } else if (SnmpGetLastError(pSMS->hSnmpSession) != SNMPAPI_NOOP) {
  660. SNMPDBG((
  661. SNMP_LOG_ERROR,
  662. "MGMTAPI: SnmpCountVbl returned %s.\n",
  663. SnmpGetLastError(pSMS->hSnmpSession)
  664. ));
  665. // re-initialize
  666. pVarBindList->len = 0;
  667. // failure
  668. fOk = FALSE;
  669. }
  670. }
  671. if (!fOk) {
  672. // cleanup any varbinds allocated
  673. SnmpUtilVarBindListFree(pVarBindList);
  674. }
  675. return fOk;
  676. }
  677. BOOL
  678. ParseVbl(
  679. PSNMP_MGR_SESSION pSMS,
  680. PTRAP_LIST_ENTRY pTLE
  681. )
  682. /*++
  683. Routine Description:
  684. Parse varbind list for trap-related varbinds.
  685. Arguments:
  686. pSMS - pointer to MGMTAPI session structure.
  687. pTLE - pointer to trap list entry.
  688. Return Values:
  689. Returns true if successful.
  690. --*/
  691. {
  692. SnmpVarBind * pVarBind;
  693. AsnObjectIdentifier * pOID;
  694. AsnNetworkAddress * pAgentAddress = NULL;
  695. AsnObjectIdentifier * pEnterpriseOID = NULL;
  696. // object identifiers to convert snmpv2 trap format
  697. static UINT _sysUpTime[] = { 1, 3, 6, 1, 2, 1, 1, 3 };
  698. static UINT _snmpTrapOID[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1 };
  699. static UINT _snmpAddress[] = { 1, 3, 6, 1, 3, 1057, 1 };
  700. static UINT _snmpTrapEnterprise[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 3 };
  701. static UINT _snmpTraps[] = { 1, 3, 6, 1, 6, 3, 1, 1, 5 };
  702. static AsnObjectIdentifier sysUpTime = DEFINE_OID(_sysUpTime);
  703. static AsnObjectIdentifier snmpTrapOID = DEFINE_OID(_snmpTrapOID);
  704. static AsnObjectIdentifier snmpAddress = DEFINE_OID(_snmpAddress);
  705. static AsnObjectIdentifier snmpTrapEnterprise = DEFINE_OID(_snmpTrapEnterprise);
  706. static AsnObjectIdentifier snmpTraps = DEFINE_OID(_snmpTraps);
  707. // validate pointers
  708. WSNMP_ASSERT(pSMS != NULL);
  709. WSNMP_ASSERT(pTLE != NULL);
  710. // validate vbl have minimum entries
  711. if (pTLE->VarBindList.len >= MINVARBINDLEN) {
  712. // point to sysUpTime varbind structure
  713. pVarBind = &pTLE->VarBindList.list[SYSUPTIMEINDEX];
  714. // verify variable is sysUpTime
  715. if ((pVarBind->value.asnType == ASN_TIMETICKS) &&
  716. !SnmpUtilOidNCmp(&pVarBind->name,
  717. &sysUpTime,
  718. sysUpTime.idLength)) {
  719. // transfer sysUpTime value to trap entry
  720. pTLE->TimeStamp = pVarBind->value.asnValue.ticks;
  721. } else {
  722. SNMPDBG((
  723. SNMP_LOG_ERROR,
  724. "MGMTAPI: Could not find sysUpTime.\n"
  725. ));
  726. goto cleanup; // bail...
  727. }
  728. // see if any additional varbinds present
  729. if (pTLE->VarBindList.len > MINVARBINDLEN) {
  730. // point to snmpTrapEnterprise varbind structure (maybe)
  731. pVarBind = &pTLE->VarBindList.list[pTLE->VarBindList.len - 1];
  732. // verify variable is snmpTrapEnterprise
  733. if ((pVarBind->value.asnType == ASN_OBJECTIDENTIFIER) &&
  734. !SnmpUtilOidNCmp(&pVarBind->name,
  735. &snmpTrapEnterprise,
  736. snmpTrapEnterprise.idLength)) {
  737. // transfer enterprise oid to list entry
  738. pTLE->EnterpriseOID = pVarBind->value.asnValue.object;
  739. // store enterprise oid for later
  740. pEnterpriseOID = &pTLE->EnterpriseOID;
  741. // modify type to avoid deallocation
  742. pVarBind->value.asnType = ASN_NULL;
  743. } else {
  744. SNMPDBG((
  745. SNMP_LOG_TRACE,
  746. "MGMTAPI: Could not find snmpTrapEnterprise.\n"
  747. ));
  748. }
  749. }
  750. // see if the agent address is present
  751. if (pTLE->VarBindList.len > MINVARBINDLEN+1) {
  752. // point to snmpAddress varbind structure (maybe)
  753. pVarBind = &pTLE->VarBindList.list[pTLE->VarBindList.len - 2];
  754. // verify variable is snmpAddress
  755. if ((pVarBind->value.asnType == SNMP_SYNTAX_IPADDR) &&
  756. !SnmpUtilOidNCmp(&pVarBind->name,
  757. &snmpAddress,
  758. snmpAddress.idLength)) {
  759. // transfer agent address oid to list entry
  760. pTLE->AgentAddress = pVarBind->value.asnValue.address;
  761. // store agent address for later
  762. pAgentAddress = &pTLE->AgentAddress;
  763. // modify type to avoid deallocation
  764. pVarBind->value.asnType = ASN_NULL;
  765. } else {
  766. SNMPDBG((
  767. SNMP_LOG_TRACE,
  768. "MGMTAPI: Could not find snmpAddress.\n"
  769. ));
  770. }
  771. }
  772. // point to snmpTrapOID varbind structure
  773. pVarBind = &pTLE->VarBindList.list[SNMPTRAPOIDINDEX];
  774. // verify variable is snmpTrapOID
  775. if ((pVarBind->value.asnType == ASN_OBJECTIDENTIFIER) &&
  776. !SnmpUtilOidNCmp(&pVarBind->name,
  777. &snmpTrapOID,
  778. snmpTrapOID.idLength)) {
  779. // retrieve pointer to oid
  780. pOID = &pVarBind->value.asnValue.object;
  781. // check for generic trap
  782. if (!SnmpUtilOidNCmp(pOID,
  783. &snmpTraps,
  784. snmpTraps.idLength)) {
  785. // validate size is one greater than root
  786. if (pOID->idLength == (snmpTraps.idLength + 1)) {
  787. // retrieve trap id
  788. // --ft:10/01/98 (bug #231344): WINSNMP gives up the V2 syntax => pOID->ids[snmpTraps.idLength] = [1..6]
  789. // --ft:10/01/98 (bug #231344): as MGMTAPI turns back to V1, we need to decrement this value.
  790. pTLE->nGenericTrap = (pOID->ids[snmpTraps.idLength])-1;
  791. // re-initialize
  792. pTLE->nSpecificTrap = 0;
  793. } else {
  794. SNMPDBG((
  795. SNMP_LOG_ERROR,
  796. "MGMTAPI: Invalid snmpTrapOID.\n"
  797. ));
  798. goto cleanup; // bail...
  799. }
  800. // check for specific trap
  801. } else if ((pEnterpriseOID != NULL) &&
  802. !SnmpUtilOidNCmp(pOID,
  803. pEnterpriseOID,
  804. pEnterpriseOID->idLength)) {
  805. // validate size is two greater than root
  806. if (pOID->idLength == (pEnterpriseOID->idLength + 2)) {
  807. // validate separator sub-identifier
  808. WSNMP_ASSERT(pOID->ids[pEnterpriseOID->idLength] == 0);
  809. // retrieve trap id
  810. pTLE->nSpecificTrap = pOID->ids[pEnterpriseOID->idLength + 1];
  811. // re-initialize
  812. pTLE->nGenericTrap = SNMP_GENERICTRAP_ENTERSPECIFIC;
  813. } else {
  814. SNMPDBG((
  815. SNMP_LOG_ERROR,
  816. "MGMTAPI: Invalid snmpTrapOID.\n"
  817. ));
  818. goto cleanup; // bail...
  819. }
  820. } else {
  821. SNMPDBG((
  822. SNMP_LOG_ERROR,
  823. "MGMTAPI: Could not identify snmpTrapOID.\n"
  824. ));
  825. goto cleanup; // bail...
  826. }
  827. } else {
  828. SNMPDBG((
  829. SNMP_LOG_ERROR,
  830. "MGMTAPI: Could not find snmpTrapOID.\n"
  831. ));
  832. goto cleanup; // bail...
  833. }
  834. // check for enterprise oid
  835. if (pEnterpriseOID != NULL) {
  836. // release snmpTrapEnterprise varbind structure
  837. SnmpUtilVarBindFree(&pTLE->VarBindList.list[pTLE->VarBindList.len - 1]);
  838. // decrement the list length as the last varbind was freed
  839. pTLE->VarBindList.len--;
  840. }
  841. // check for agent address
  842. if (pAgentAddress != NULL) {
  843. // release snmpAgentAddress varbind structure
  844. SnmpUtilVarBindFree(&pTLE->VarBindList.list[pTLE->VarBindList.len - 1]);
  845. // decrement the list length as the last varbind was again freed
  846. pTLE->VarBindList.len--;
  847. }
  848. // release sysUpTime varbind structure
  849. SnmpUtilVarBindFree(&pTLE->VarBindList.list[SYSUPTIMEINDEX]);
  850. // release snmpTrapOID varbind structure
  851. SnmpUtilVarBindFree(&pTLE->VarBindList.list[SNMPTRAPOIDINDEX]);
  852. // subtract released varbinds
  853. pTLE->VarBindList.len -= MINVARBINDLEN;
  854. // check if all varbinds freed
  855. if (pTLE->VarBindList.len == 0) {
  856. // release memory for list
  857. SnmpUtilMemFree(pTLE->VarBindList.list);
  858. // re-initialize
  859. pTLE->VarBindList.list = NULL;
  860. } else {
  861. // shift varbind list up two spaces
  862. memmove((LPBYTE)(pTLE->VarBindList.list),
  863. (LPBYTE)(pTLE->VarBindList.list + MINVARBINDLEN),
  864. (pTLE->VarBindList.len * sizeof(SnmpVarBind))
  865. );
  866. }
  867. } else {
  868. SNMPDBG((
  869. SNMP_LOG_ERROR,
  870. "MGMTAPI: Too few subidentifiers.\n"
  871. ));
  872. }
  873. // success
  874. return TRUE;
  875. cleanup:
  876. // failure
  877. return FALSE;
  878. }
  879. BOOL
  880. FreeTle(
  881. PTRAP_LIST_ENTRY pTLE
  882. )
  883. /*++
  884. Routine Description:
  885. Release memory used for trap entry.
  886. Arguments:
  887. pTLE - pointer to trap list entry.
  888. Return Values:
  889. Returns true if successful.
  890. --*/
  891. {
  892. // validate pointer
  893. WSNMP_ASSERT(pTLE != NULL);
  894. // release memory for enterprise oid if necessary
  895. SnmpUtilOidFree(&pTLE->EnterpriseOID);
  896. // release memory for AgentAddress if necessary
  897. SnmpUtilOctetsFree(&pTLE->AgentAddress); // AgentAddress is a AsnOctetString type
  898. // release memory for SourceAddress if necessary
  899. SnmpUtilOctetsFree(&pTLE->SourceAddress); // SourceAddress is a AsnOctetString type
  900. // release memory for community string if necessary
  901. SnmpUtilMemFree(pTLE->Community.stream);
  902. // release memory used in varbind list if necessary
  903. SnmpUtilVarBindListFree(&pTLE->VarBindList);
  904. // release list entry
  905. SnmpUtilMemFree(pTLE);
  906. return TRUE;
  907. }
  908. BOOL
  909. AllocateTle(
  910. PSNMP_MGR_SESSION pSMS,
  911. PTRAP_LIST_ENTRY * ppTLE,
  912. HSNMP_ENTITY hAgentEntity,
  913. HSNMP_CONTEXT hViewContext
  914. )
  915. /*++
  916. Routine Description:
  917. Allocate memory for trap entry.
  918. Arguments:
  919. pSMS - pointer to MGMTAPI session structure.
  920. ppTLE - pointer to pointer to trap list entry.
  921. hAgentEntity - handle to agent sending trap.
  922. hViewContext - handle to view context of trap.
  923. Return Values:
  924. Returns true if successful.
  925. --*/
  926. {
  927. PTRAP_LIST_ENTRY pTLE;
  928. SNMPAPI_STATUS status;
  929. smiOCTETS CommunityStr;
  930. CHAR SourceStrAddr[MAXENTITYSTRLEN+1];
  931. struct sockaddr SourceSockAddr;
  932. // validate pointers
  933. WSNMP_ASSERT(pSMS != NULL);
  934. WSNMP_ASSERT(ppTLE != NULL);
  935. // allocate memory from list entry
  936. pTLE = SnmpUtilMemAlloc(sizeof(TRAP_LIST_ENTRY));
  937. // validate pointer
  938. if (pTLE == NULL) {
  939. SNMPDBG((
  940. SNMP_LOG_ERROR,
  941. "MGMTAPI: Could not allocate trap entry.\n"
  942. ));
  943. return FALSE; // bail...
  944. }
  945. // initialize
  946. *ppTLE = NULL;
  947. // copy varbinds to trap list entry
  948. if (!CopyVbl(pSMS, &pTLE->VarBindList)) {
  949. goto cleanup; // bail...
  950. }
  951. // parse trap-related varbinds
  952. if (!ParseVbl(pSMS, pTLE)) {
  953. goto cleanup; // bail...
  954. }
  955. // check if source address is specified
  956. if (hAgentEntity != (HSNMP_ENTITY)NULL) {
  957. // convert addr to string
  958. status = SnmpEntityToStr(
  959. hAgentEntity,
  960. sizeof(SourceStrAddr),
  961. SourceStrAddr
  962. );
  963. // validate error code
  964. if (WSNMP_SUCCEEDED(status)) {
  965. DWORD AddrLen = 0;
  966. LPBYTE AddrPtr = NULL;
  967. // convert string to socket address structure
  968. if (! SnmpSvcAddrToSocket(SourceStrAddr, &SourceSockAddr))
  969. {
  970. SNMPDBG((
  971. SNMP_LOG_ERROR,
  972. "MGMTAPI: Ignoring invalid address.\n"
  973. ));
  974. goto cleanup; // bail...
  975. }
  976. // validate address family
  977. if (SourceSockAddr.sa_family == AF_INET) {
  978. // assign ip values
  979. AddrLen = IPADDRLEN;
  980. AddrPtr = (LPBYTE)&(((struct sockaddr_in *)
  981. (&SourceSockAddr))->sin_addr);
  982. } else if (SourceSockAddr.sa_family == AF_IPX) {
  983. // assign ipx values
  984. AddrLen = IPXADDRLEN;
  985. AddrPtr = (LPBYTE)&(((struct sockaddr_ipx *)
  986. (&SourceSockAddr))->sa_netnum);
  987. } else {
  988. SNMPDBG((
  989. SNMP_LOG_ERROR,
  990. "MGMTAPI: Ignoring invalid address.\n"
  991. ));
  992. goto cleanup; // bail...
  993. }
  994. // allocate address to return (if specified)
  995. pTLE->SourceAddress.stream = SnmpUtilMemAlloc(AddrLen);
  996. // validate pointer
  997. if (pTLE->SourceAddress.stream != NULL) {
  998. // initialize length values
  999. pTLE->SourceAddress.length = AddrLen;
  1000. pTLE->SourceAddress.dynamic = TRUE;
  1001. // transfer agent address information
  1002. memcpy(pTLE->SourceAddress.stream, AddrPtr, AddrLen);
  1003. }
  1004. } else {
  1005. SNMPDBG((
  1006. SNMP_LOG_ERROR,
  1007. "MGMTAPI: SnmpEntityToStr returned %d.\n",
  1008. SnmpGetLastError((HSNMP_SESSION)NULL)
  1009. ));
  1010. goto cleanup; // bail...
  1011. }
  1012. }
  1013. // check if community specified
  1014. if (hViewContext != (HSNMP_CONTEXT)NULL) {
  1015. // convert agent entity to string
  1016. status = SnmpContextToStr(hViewContext, &CommunityStr);
  1017. // validate error code
  1018. if (WSNMP_SUCCEEDED(status)) {
  1019. // copy octet string, memory allocated in CommunityStr is also freed
  1020. CopyOctets(&pTLE->Community, &CommunityStr);
  1021. } else {
  1022. SNMPDBG((
  1023. SNMP_LOG_ERROR,
  1024. "MGMTAPI: SnmpContextToStr returned %d.\n",
  1025. SnmpGetLastError((HSNMP_SESSION)NULL)
  1026. ));
  1027. goto cleanup; // bail...
  1028. }
  1029. }
  1030. // transfer
  1031. *ppTLE = pTLE;
  1032. // success
  1033. return TRUE;
  1034. cleanup:
  1035. // release
  1036. FreeTle(pTLE);
  1037. // failure
  1038. return FALSE;
  1039. }
  1040. BOOL
  1041. NotificationCallback(
  1042. PSNMP_MGR_SESSION pSMS
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. Callback for processing notification messages.
  1047. Arguments:
  1048. pSMS - pointer to mgmtapi session structure.
  1049. Return Values:
  1050. Returns true if processing finished.
  1051. --*/
  1052. {
  1053. BOOL fDone = TRUE;
  1054. SNMPAPI_STATUS status;
  1055. HSNMP_ENTITY hAgentEntity = (HSNMP_ENTITY)NULL;
  1056. HSNMP_ENTITY hManagerEntity = (HSNMP_ENTITY)NULL;
  1057. HSNMP_CONTEXT hViewContext = (HSNMP_CONTEXT)NULL;
  1058. smiINT32 nPduType;
  1059. smiINT32 nRequestId;
  1060. // validate pointer
  1061. WSNMP_ASSERT(pSMS != NULL);
  1062. // retrieve message
  1063. status = SnmpRecvMsg(
  1064. pSMS->hSnmpSession,
  1065. &hAgentEntity,
  1066. &hManagerEntity,
  1067. &hViewContext,
  1068. &pSMS->hPdu
  1069. );
  1070. // validate return code
  1071. if (WSNMP_SUCCEEDED(status)) {
  1072. // retrieve pdu data
  1073. status = SnmpGetPduData(
  1074. pSMS->hPdu,
  1075. &nPduType,
  1076. &nRequestId,
  1077. &pSMS->nErrorStatus,
  1078. &pSMS->nErrorIndex,
  1079. &pSMS->hVbl
  1080. );
  1081. // validate return code
  1082. if (WSNMP_SUCCEEDED(status)) {
  1083. // process reponse to request
  1084. if (nPduType == SNMP_PDU_RESPONSE) {
  1085. // validate context information
  1086. if ((pSMS->nRequestId == nRequestId) &&
  1087. (pSMS->hViewContext == hViewContext) &&
  1088. (pSMS->hAgentEntity == hAgentEntity) &&
  1089. (pSMS->hManagerEntity == hManagerEntity)) {
  1090. // validate returned error status
  1091. if (pSMS->nErrorStatus == SNMP_ERROR_NOERROR) {
  1092. SnmpVarBindList VarBindList;
  1093. // copy variable binding list
  1094. if (CopyVbl(pSMS, &VarBindList)) {
  1095. // release existing varbind list
  1096. SnmpUtilVarBindListFree(pSMS->pVarBindList);
  1097. // manually copy new varbind list
  1098. *pSMS->pVarBindList = VarBindList;
  1099. } else {
  1100. // modify last error status
  1101. pSMS->nLastError = SNMPAPI_ALLOC_ERROR;
  1102. }
  1103. }
  1104. } else {
  1105. SNMPDBG((
  1106. SNMP_LOG_TRACE,
  1107. "MGMTAPI: Ignoring invalid context.\n"
  1108. ));
  1109. // continue
  1110. fDone = FALSE;
  1111. }
  1112. } else if (nPduType == SNMP_PDU_TRAP) {
  1113. PTRAP_LIST_ENTRY pTLE;
  1114. // allocate trap list entry (transfers varbinds etc.)
  1115. if (AllocateTle(pSMS, &pTLE, hAgentEntity, hViewContext)) {
  1116. // obtain exclusive access
  1117. EnterCriticalSection(&g_GlobalLock);
  1118. // insert new trap into the incoming queue
  1119. InsertTailList(&g_IncomingTraps, &pTLE->Link);
  1120. // alert user
  1121. SetEvent(g_hTrapEvent);
  1122. // release exclusive access
  1123. LeaveCriticalSection(&g_GlobalLock);
  1124. }
  1125. } else {
  1126. SNMPDBG((
  1127. SNMP_LOG_ERROR,
  1128. "MGMTAPI: Ignoring invalid pdu type %d.\n",
  1129. nPduType
  1130. ));
  1131. // continue
  1132. fDone = FALSE;
  1133. }
  1134. } else {
  1135. SNMPDBG((
  1136. SNMP_LOG_ERROR,
  1137. "MGMTAPI: SnmpGetPduData returned %d.\n",
  1138. SnmpGetLastError(pSMS->hSnmpSession)
  1139. ));
  1140. // retrieve last error status from winsnmp
  1141. pSMS->nLastError = SnmpGetLastError(pSMS->hSnmpSession);
  1142. }
  1143. // release temporary entity
  1144. SnmpFreeEntity(hAgentEntity);
  1145. // release temporary entity
  1146. SnmpFreeEntity(hManagerEntity);
  1147. // release temporary context
  1148. SnmpFreeContext(hViewContext);
  1149. } else {
  1150. SNMPDBG((
  1151. SNMP_LOG_ERROR,
  1152. "MGMTAPI: SnmpRecvMsg returned %d.\n",
  1153. SnmpGetLastError(pSMS->hSnmpSession)
  1154. ));
  1155. // retrieve last error status from winsnmp
  1156. pSMS->nLastError = SnmpGetLastError(pSMS->hSnmpSession);
  1157. }
  1158. // release pdu
  1159. FreePdu(pSMS);
  1160. return fDone;
  1161. }
  1162. LRESULT
  1163. CALLBACK
  1164. NotificationWndProc(
  1165. HWND hWnd,
  1166. UINT uMsg,
  1167. WPARAM wParam,
  1168. LPARAM lParam
  1169. )
  1170. /*++
  1171. Routine Description:
  1172. Callback that processes WinSNMP notifications.
  1173. Arguments:
  1174. hWnd - window handle.
  1175. uMsg - message identifier.
  1176. wParam - first message parameter.
  1177. lParam - second message parameter.
  1178. Return Values:
  1179. The return value is the result of the message processing and
  1180. depends on the message sent.
  1181. --*/
  1182. {
  1183. // check for winsnmp notification and transport timeout
  1184. if (uMsg == WM_WSNMP_INCOMING && wParam == SNMPAPI_TL_TIMEOUT) {
  1185. PSNMP_MGR_SESSION pSMS;
  1186. // retrieve mgmtapi session pointer from window
  1187. pSMS = (PSNMP_MGR_SESSION)GetWindowLongPtr(hWnd, 0);
  1188. // validate session ptr
  1189. WSNMP_ASSERT(pSMS != NULL);
  1190. // translate winsnmp error to mgmtapi error
  1191. pSMS->nLastError = SNMP_MGMTAPI_TIMEOUT;
  1192. // post message to break out of message pump
  1193. PostMessage(pSMS->hWnd, WM_WSNMP_DONE, (WPARAM)0, (LPARAM)0);
  1194. return (LRESULT)0;
  1195. }
  1196. // check for winsnmp notification
  1197. else if (uMsg == WM_WSNMP_INCOMING) {
  1198. PSNMP_MGR_SESSION pSMS;
  1199. // retrieve mgmtapi session pointer from window
  1200. pSMS = (PSNMP_MGR_SESSION)GetWindowLongPtr(hWnd, 0);
  1201. // validate session ptr
  1202. WSNMP_ASSERT(pSMS != NULL);
  1203. // process notification message
  1204. if (NotificationCallback(pSMS)) {
  1205. // post message to break out of message pump
  1206. PostMessage(pSMS->hWnd, WM_WSNMP_DONE, (WPARAM)0, (LPARAM)0);
  1207. }
  1208. return (LRESULT)0;
  1209. } else {
  1210. // forward all other messages to windows
  1211. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  1212. }
  1213. }
  1214. BOOL
  1215. RegisterNotificationClass(
  1216. )
  1217. /*++
  1218. Routine Description:
  1219. Register notification class for sessions.
  1220. Arguments:
  1221. None.
  1222. Return Values:
  1223. Returns true if successful.
  1224. --*/
  1225. {
  1226. BOOL fOk;
  1227. WNDCLASS wc;
  1228. // initialize notification window class
  1229. wc.lpfnWndProc = NotificationWndProc;
  1230. wc.lpszClassName = NOTIFICATION_CLASS;
  1231. wc.lpszMenuName = NULL;
  1232. wc.hInstance = g_hDll;
  1233. wc.hIcon = NULL;
  1234. wc.hCursor = NULL;
  1235. wc.hbrBackground = NULL;
  1236. wc.cbWndExtra = sizeof(PSNMP_MGR_SESSION);
  1237. wc.cbClsExtra = 0;
  1238. wc.style = 0;
  1239. // register class
  1240. fOk = RegisterClass(&wc);
  1241. if (!fOk) {
  1242. SNMPDBG((
  1243. SNMP_LOG_ERROR,
  1244. "MGMTAPI: RegisterClass returned %d.\n",
  1245. GetLastError()
  1246. ));
  1247. }
  1248. return fOk;
  1249. }
  1250. BOOL
  1251. UnregisterNotificationClass(
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. Unregister notification class.
  1256. Arguments:
  1257. None.
  1258. Return Values:
  1259. Returns true if successful.
  1260. --*/
  1261. {
  1262. BOOL fOk;
  1263. // unergister notification window class
  1264. fOk = UnregisterClass(NOTIFICATION_CLASS, g_hDll);
  1265. if (!fOk) {
  1266. SNMPDBG((
  1267. SNMP_LOG_ERROR,
  1268. "MGMTAPI: UnregisterClass returned %d.\n",
  1269. GetLastError()
  1270. ));
  1271. }
  1272. return fOk;
  1273. }
  1274. BOOL
  1275. StartSnmpIfNecessary(
  1276. )
  1277. /*++
  1278. Routine Description:
  1279. Initialize WinSNMP DLL if necessary.
  1280. Arguments:
  1281. None.
  1282. Return Values:
  1283. Returns true if successful.
  1284. --*/
  1285. {
  1286. BOOL fOk;
  1287. // serialize access to startup code
  1288. EnterCriticalSection(&g_GlobalLock);
  1289. // see if already started
  1290. if (g_fIsSnmpStarted != TRUE) {
  1291. SNMPAPI_STATUS status;
  1292. // initialize start params
  1293. smiUINT32 nMajorVersion = 0;
  1294. smiUINT32 nMinorVersion = 0;
  1295. smiUINT32 nLevel = 0;
  1296. smiUINT32 nTranslateMode = 0;
  1297. smiUINT32 nRetransmitMode = 0;
  1298. // start winsnmp
  1299. status = SnmpStartup(
  1300. &nMajorVersion,
  1301. &nMinorVersion,
  1302. &nLevel,
  1303. &nTranslateMode,
  1304. &nRetransmitMode
  1305. );
  1306. // validate return code
  1307. if (WSNMP_SUCCEEDED(status)) {
  1308. SNMPDBG((
  1309. SNMP_LOG_TRACE,
  1310. "MGMTAPI: SnmpStartup succeeded:\n"
  1311. "MGMTAPI:\tnMajorVersion = %d\n"
  1312. "MGMTAPI:\tnMinorVersion = %d\n"
  1313. "MGMTAPI:\tnLevel = %d\n"
  1314. "MGMTAPI:\tnTranslateMode = %d\n"
  1315. "MGMTAPI:\tnRetransmitMode = %d\n",
  1316. nMajorVersion,
  1317. nMinorVersion,
  1318. nLevel,
  1319. nTranslateMode,
  1320. nRetransmitMode
  1321. ));
  1322. // allocate global trap available event
  1323. if ((g_hTrapEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
  1324. {
  1325. SNMPDBG((
  1326. SNMP_LOG_ERROR,
  1327. "MGMTAPI: CreateEvent returned %d.\n",
  1328. GetLastError()
  1329. ));
  1330. // failure
  1331. goto cleanup;
  1332. }
  1333. // allocate global event to sync. SnmpMgrTrapListen
  1334. if ((g_hTrapRegisterdEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) ==NULL)
  1335. {
  1336. SNMPDBG((
  1337. SNMP_LOG_ERROR,
  1338. "MGMTAPI: CreateEvent returned %d.\n",
  1339. GetLastError()
  1340. ));
  1341. // failure
  1342. goto cleanup;
  1343. }
  1344. // make sure translate mode is snmp v1
  1345. status = SnmpSetTranslateMode(SNMPAPI_UNTRANSLATED_V1);
  1346. if (WSNMP_FAILED(status))
  1347. {
  1348. SNMPDBG((
  1349. SNMP_LOG_ERROR,
  1350. "MGMTAPI: SnmpSetTranslateMode returned %d.\n",
  1351. SnmpGetLastError((HSNMP_SESSION)NULL)
  1352. ));
  1353. // failure
  1354. goto cleanup;
  1355. }
  1356. // make sure retransmit mode is on
  1357. status = SnmpSetRetransmitMode(SNMPAPI_ON);
  1358. if (WSNMP_FAILED(status))
  1359. {
  1360. SNMPDBG((
  1361. SNMP_LOG_ERROR,
  1362. "MGMTAPI: SnmpSetRetransmitMode returned %d.\n",
  1363. SnmpGetLastError((HSNMP_SESSION)NULL)
  1364. ));
  1365. // failure
  1366. goto cleanup;
  1367. }
  1368. // register notification class
  1369. if (!RegisterNotificationClass())
  1370. {
  1371. SNMPDBG((
  1372. SNMP_LOG_ERROR,
  1373. "MGMTAPI: RegisterNotificationClass returned %d.\n",
  1374. GetLastError()
  1375. ));
  1376. // failure
  1377. goto cleanup;
  1378. }
  1379. // save new status
  1380. g_fIsSnmpStarted = TRUE;
  1381. // success
  1382. fOk = TRUE;
  1383. } else {
  1384. SNMPDBG((
  1385. SNMP_LOG_ERROR,
  1386. "MGMTAPI: SnmpStartup returned %d.\n",
  1387. SnmpGetLastError((HSNMP_SESSION)NULL)
  1388. ));
  1389. // failure, but no need to cleanup
  1390. fOk = FALSE;
  1391. }
  1392. } else {
  1393. fOk = TRUE;
  1394. }
  1395. // serialize access to startup code
  1396. LeaveCriticalSection(&g_GlobalLock);
  1397. return fOk;
  1398. cleanup:
  1399. // cleanup if necessary
  1400. SnmpCleanup(); // ignore any return status at this stage
  1401. if (g_hTrapEvent)
  1402. {
  1403. CloseHandle(g_hTrapEvent);
  1404. g_hTrapEvent = NULL;
  1405. }
  1406. if (g_hTrapRegisterdEvent)
  1407. {
  1408. CloseHandle(g_hTrapRegisterdEvent);
  1409. g_hTrapRegisterdEvent = NULL;
  1410. }
  1411. LeaveCriticalSection(&g_GlobalLock);
  1412. return FALSE;
  1413. }
  1414. BOOL
  1415. CleanupIfNecessary(
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. Cleanup WinSNMP DLL if necessary.
  1420. Arguments:
  1421. None.
  1422. Return Values:
  1423. Returns true if successful.
  1424. --*/
  1425. {
  1426. BOOL fOk = TRUE;
  1427. // serialize access to startup code
  1428. EnterCriticalSection(&g_GlobalLock);
  1429. // see if already started
  1430. if (g_fIsSnmpStarted == TRUE) {
  1431. SNMPAPI_STATUS status;
  1432. // shutdown winsnmp
  1433. status = SnmpCleanup();
  1434. // validate return code
  1435. if (WSNMP_FAILED(status)) {
  1436. SNMPDBG((
  1437. SNMP_LOG_ERROR,
  1438. "MGMTAPI: SnmpCleanup returned %d.\n",
  1439. SnmpGetLastError((HSNMP_SESSION)NULL)
  1440. ));
  1441. // failure
  1442. fOk = FALSE;
  1443. }
  1444. // unregister notification class
  1445. UnregisterNotificationClass();
  1446. // save new status
  1447. g_fIsSnmpStarted = FALSE;
  1448. }
  1449. // check trap handle
  1450. if (g_hTrapEvent != NULL) {
  1451. // close trap handle
  1452. CloseHandle(g_hTrapEvent);
  1453. // re-initialize
  1454. g_hTrapEvent = NULL;
  1455. }
  1456. // check event that syncs SnmpMgrTrapListen
  1457. if (g_hTrapRegisterdEvent != NULL)
  1458. {
  1459. // close trap handle
  1460. CloseHandle(g_hTrapRegisterdEvent);
  1461. // re-initialize
  1462. g_hTrapRegisterdEvent = NULL;
  1463. }
  1464. // serialize access to startup code
  1465. LeaveCriticalSection(&g_GlobalLock);
  1466. return fOk;
  1467. }
  1468. DWORD AddMgmtRef()
  1469. /*++
  1470. Routine Description:
  1471. Increment the reference count on using the mgmtapi.dll module.
  1472. Arguments:
  1473. none
  1474. Return Values:
  1475. Returns the reference count value after the increment is done.
  1476. --*/
  1477. {
  1478. EnterCriticalSection(&g_GlobalLock);
  1479. ++g_cSnmpMgmtRef;
  1480. LeaveCriticalSection(&g_GlobalLock);
  1481. return g_cSnmpMgmtRef;
  1482. }
  1483. DWORD ReleaseMgmtRef()
  1484. /*++
  1485. Routine Description:
  1486. Decrement the reference count if it is greater than zero.
  1487. Call CleanupIfNecessary if the reference count on using mgmtapi.dll becomes
  1488. zero after the decrement.
  1489. Arguments:
  1490. none
  1491. Return Values:
  1492. Returns the final reference count value.
  1493. --*/
  1494. {
  1495. EnterCriticalSection(&g_GlobalLock);
  1496. if (g_cSnmpMgmtRef)
  1497. {
  1498. --g_cSnmpMgmtRef;
  1499. if (g_cSnmpMgmtRef == 0)
  1500. {
  1501. CleanupIfNecessary();
  1502. }
  1503. }
  1504. LeaveCriticalSection(&g_GlobalLock);
  1505. return g_cSnmpMgmtRef;
  1506. }
  1507. BOOL
  1508. CreateNotificationWindow(
  1509. PSNMP_MGR_SESSION pSMS
  1510. )
  1511. /*++
  1512. Routine Description:
  1513. Create notification window for session.
  1514. Arguments:
  1515. pSMS - pointer to MGMTAPI session structure.
  1516. Return Values:
  1517. Returns true if successful.
  1518. --*/
  1519. {
  1520. BOOL fOk;
  1521. // validate session ptr
  1522. WSNMP_ASSERT(pSMS != NULL);
  1523. // create notification window
  1524. pSMS->hWnd = CreateWindow(
  1525. NOTIFICATION_CLASS,
  1526. NULL, // pointer to window name
  1527. 0, // window style
  1528. 0, // horizontal position of window
  1529. 0, // vertical position of window
  1530. 0, // window width
  1531. 0, // window height
  1532. NULL, // handle to parent or owner window
  1533. NULL, // handle to menu or child-window identifier
  1534. g_hDll, // handle to application instance
  1535. NULL // pointer to window-creation data
  1536. );
  1537. // validate window handle
  1538. if (pSMS->hWnd != NULL) {
  1539. // store pointer to session in window
  1540. SetWindowLongPtr(pSMS->hWnd, 0, (LONG_PTR)pSMS);
  1541. // success
  1542. fOk = TRUE;
  1543. } else {
  1544. SNMPDBG((
  1545. SNMP_LOG_ERROR,
  1546. "MGMTAPI: CreateWindow returned %d.\n",
  1547. GetLastError()
  1548. ));
  1549. // failure
  1550. fOk = FALSE;
  1551. }
  1552. return fOk;
  1553. }
  1554. BOOL
  1555. DestroyNotificationWindow(
  1556. HWND hWnd
  1557. )
  1558. /*++
  1559. Routine Description:
  1560. Destroy notification window for session.
  1561. Arguments:
  1562. hWnd - window handle for session.
  1563. Return Values:
  1564. Returns true if successful.
  1565. --*/
  1566. {
  1567. BOOL fOk;
  1568. // destroy notification window
  1569. fOk = DestroyWindow(hWnd);
  1570. if (!fOk) {
  1571. SNMPDBG((
  1572. SNMP_LOG_ERROR,
  1573. "MGMTAPI: DestroyWindow returned %d.\n",
  1574. GetLastError()
  1575. ));
  1576. }
  1577. return fOk;
  1578. }
  1579. BOOL
  1580. CloseSession(
  1581. PSNMP_MGR_SESSION pSMS
  1582. )
  1583. /*++
  1584. Routine Description:
  1585. Close WinSNMP session associated with MGMTAPI session.
  1586. Arguments:
  1587. pSMS - pointer to MGMTAPI session structure.
  1588. Return Values:
  1589. Returns true if successful.
  1590. --*/
  1591. {
  1592. BOOL fOk = TRUE;
  1593. SNMPAPI_STATUS status;
  1594. // validate session ptr
  1595. WSNMP_ASSERT(pSMS != NULL);
  1596. // check if window opened
  1597. if (pSMS->hWnd != (HWND)NULL) {
  1598. // destroy notification window
  1599. fOk = DestroyNotificationWindow(pSMS->hWnd);
  1600. }
  1601. // check if agent entity allocated
  1602. if (pSMS->hAgentEntity != (HSNMP_ENTITY)NULL) {
  1603. // close the entity handle
  1604. status = SnmpFreeEntity(pSMS->hAgentEntity);
  1605. // validate status
  1606. if (WSNMP_FAILED(status)) {
  1607. SNMPDBG((
  1608. SNMP_LOG_ERROR,
  1609. "MGMTAPI: SnmpFreeEntity returned %d.\n",
  1610. SnmpGetLastError((HSNMP_SESSION)NULL)
  1611. ));
  1612. // failure
  1613. fOk = FALSE;
  1614. }
  1615. // re-initialize
  1616. pSMS->hAgentEntity = (HSNMP_ENTITY)NULL;
  1617. }
  1618. // check if manager entity allocated
  1619. if (pSMS->hManagerEntity != (HSNMP_ENTITY)NULL) {
  1620. // close the entity handle
  1621. status = SnmpFreeEntity(pSMS->hManagerEntity);
  1622. // validate status
  1623. if (WSNMP_FAILED(status)) {
  1624. SNMPDBG((
  1625. SNMP_LOG_ERROR,
  1626. "MGMTAPI: SnmpFreeEntity returned %d.\n",
  1627. SnmpGetLastError((HSNMP_SESSION)NULL)
  1628. ));
  1629. // failure
  1630. fOk = FALSE;
  1631. }
  1632. // re-initialize
  1633. pSMS->hManagerEntity = (HSNMP_ENTITY)NULL;
  1634. }
  1635. // check if session allocated
  1636. if (pSMS->hSnmpSession != (HSNMP_SESSION)NULL) {
  1637. // close the winsnmp session
  1638. status = SnmpClose(pSMS->hSnmpSession);
  1639. // validate status
  1640. if (WSNMP_FAILED(status)) {
  1641. SNMPDBG((
  1642. SNMP_LOG_ERROR,
  1643. "MGMTAPI: SnmpClose returned %d.\n",
  1644. SnmpGetLastError((HSNMP_SESSION)NULL)
  1645. ));
  1646. // failure
  1647. fOk = FALSE;
  1648. }
  1649. // re-initialize
  1650. pSMS->hSnmpSession = (HSNMP_SESSION)NULL;
  1651. }
  1652. return fOk;
  1653. }
  1654. //SNMPAPI_STATUS SNMPAPI_CALL
  1655. // SnmpConveyAgentAddress (SNMPAPI_STATUS mode);
  1656. BOOL
  1657. OpenSession(
  1658. PSNMP_MGR_SESSION pSMS,
  1659. LPSTR pAgentAddress,
  1660. LPSTR pAgentCommunity,
  1661. INT nTimeOut,
  1662. INT nRetries
  1663. )
  1664. /*++
  1665. Routine Description:
  1666. Open WinSNMP session and associate with MGMTAPI session.
  1667. Arguments:
  1668. pSMS - pointer to MGMTAPI session structure.
  1669. pAgentAddress - points to a null-terminated string specifying either a
  1670. dotted-decimal IP address or a host name that can be resolved to an
  1671. IP address, an IPX address (in 8.12 notation), or an ethernet address.
  1672. pAgentCommunity - points to a null-terminated string specifying the
  1673. SNMP community name used when communicating with the agent specified
  1674. in the lpAgentAddress parameter
  1675. nTimeOut - specifies the communications time-out in milliseconds.
  1676. nRetries - specifies the communications retry count.
  1677. Return Values:
  1678. Returns true if successful.
  1679. --*/
  1680. {
  1681. BOOL fOk;
  1682. struct sockaddr AgentSockAddr;
  1683. CHAR AgentStrAddr[MAXENTITYSTRLEN+1];
  1684. smiOCTETS smiCommunity;
  1685. SNMPAPI_STATUS status;
  1686. // validate session ptr
  1687. WSNMP_ASSERT(pSMS != NULL);
  1688. // initialize notification window
  1689. if (!CreateNotificationWindow(pSMS)) {
  1690. return FALSE; // bail...
  1691. }
  1692. // open a winsnmp session which corresponds to mgmtapi session
  1693. pSMS->hSnmpSession = SnmpOpen(pSMS->hWnd, WM_WSNMP_INCOMING);
  1694. // --ft
  1695. // we need to turn this on in order to have WINSNMP to pass back not
  1696. // only the entity standing for the source Ip address but also the
  1697. // agent address as it was sent into the V1 Trap Pdu. Without it,
  1698. // SnmpMgrGetTrapEx() will return a NULL address for the pSourceAddress
  1699. // paramter. However, SnmpMgrGetTrapEx() is not documented!!!
  1700. //SnmpConveyAgentAddress(SNMPAPI_ON); // Move this into wsnmp_cf.c:SnmpStartup
  1701. // to avoid missing entry point problem when wsnmp32.dll is from other vendors
  1702. // validate session handle returned
  1703. if (WSNMP_FAILED(pSMS->hSnmpSession)) {
  1704. SNMPDBG((
  1705. SNMP_LOG_ERROR,
  1706. "MGMTAPI: SnmpOpen returned %d.\n",
  1707. SnmpGetLastError((HSNMP_SESSION)NULL)
  1708. ));
  1709. // re-initialize
  1710. pSMS->hSnmpSession = (HSNMP_SESSION)NULL;
  1711. goto cleanup; // bail...
  1712. }
  1713. // validate pointer
  1714. if (pAgentAddress != NULL) {
  1715. AgentStrAddr[MAXENTITYSTRLEN] = '\0';
  1716. // use snmpapi.dll to do convert to sockets structure
  1717. if (!SnmpSvcAddrToSocket(pAgentAddress, &AgentSockAddr)) {
  1718. SNMPDBG((
  1719. SNMP_LOG_ERROR,
  1720. "MGMTAPI: Ignoring invalid address.\n"
  1721. ));
  1722. goto cleanup; // bail...
  1723. }
  1724. // check address family of agent
  1725. if (AgentSockAddr.sa_family == AF_INET) {
  1726. LPSTR pAgentStrAddr;
  1727. struct sockaddr_in * pAgentSockAddr;
  1728. // cast generic socket address structure to inet
  1729. pAgentSockAddr = (struct sockaddr_in *)&AgentSockAddr;
  1730. // obtain exclusive access to api
  1731. EnterCriticalSection(&g_GlobalLock);
  1732. // attempt to convert address into string
  1733. pAgentStrAddr = inet_ntoa(pAgentSockAddr->sin_addr);
  1734. // copy to stack variable
  1735. strncpy(AgentStrAddr, pAgentStrAddr, MAXENTITYSTRLEN);
  1736. // release exclusive access to api
  1737. LeaveCriticalSection(&g_GlobalLock);
  1738. } else if (AgentSockAddr.sa_family == AF_IPX) {
  1739. // simply copy original string
  1740. strncpy(AgentStrAddr, pAgentAddress, MAXENTITYSTRLEN);
  1741. } else {
  1742. SNMPDBG((
  1743. SNMP_LOG_ERROR,
  1744. "MGMTAPI: Incorrect address family.\n"
  1745. ));
  1746. goto cleanup; // bail...
  1747. }
  1748. // create remote agent entity
  1749. pSMS->hAgentEntity = SnmpStrToEntity(
  1750. pSMS->hSnmpSession,
  1751. AgentStrAddr
  1752. );
  1753. // validate agent entity returned
  1754. if (WSNMP_FAILED(pSMS->hAgentEntity)) {
  1755. SNMPDBG((
  1756. SNMP_LOG_ERROR,
  1757. "MGMTAPI: SnmpStrToEntity returned %d.\n",
  1758. SnmpGetLastError(pSMS->hSnmpSession)
  1759. ));
  1760. // re-initialize
  1761. pSMS->hAgentEntity = (HSNMP_ENTITY)NULL;
  1762. goto cleanup; // bail...
  1763. }
  1764. // attach timeout specified with agent
  1765. status = SnmpSetTimeout(pSMS->hAgentEntity, nTimeOut / 10);
  1766. if (WSNMP_FAILED(status)) {
  1767. SNMPDBG((
  1768. SNMP_LOG_ERROR,
  1769. "MGMTAPI: SnmpSetTimeout returned %d.\n",
  1770. SnmpGetLastError((HSNMP_SESSION)NULL)
  1771. ));
  1772. goto cleanup; // bail...
  1773. }
  1774. // attach retries specified with agent
  1775. status = SnmpSetRetry(pSMS->hAgentEntity, nRetries);
  1776. if (WSNMP_FAILED(status)) {
  1777. SNMPDBG((
  1778. SNMP_LOG_ERROR,
  1779. "MGMTAPI: SnmpSetRetry returned %d.\n",
  1780. SnmpGetLastError((HSNMP_SESSION)NULL)
  1781. ));
  1782. goto cleanup; // bail...
  1783. }
  1784. // create local manager entity
  1785. pSMS->hManagerEntity = SnmpStrToEntity(
  1786. pSMS->hSnmpSession,
  1787. (AgentSockAddr.sa_family == AF_INET)
  1788. ? DEFAULT_ADDRESS_IP
  1789. : DEFAULT_ADDRESS_IPX
  1790. );
  1791. // validate manager entity returned
  1792. if (WSNMP_FAILED(pSMS->hManagerEntity)) {
  1793. SNMPDBG((
  1794. SNMP_LOG_ERROR,
  1795. "MGMTAPI: SnmpStrToEntity returned %d.\n",
  1796. SnmpGetLastError(pSMS->hSnmpSession)
  1797. ));
  1798. // re-initialize
  1799. pSMS->hManagerEntity = (HSNMP_ENTITY)NULL;
  1800. goto cleanup; // bail...
  1801. }
  1802. // attach timeout specified with manager
  1803. status = SnmpSetTimeout(pSMS->hManagerEntity, nTimeOut / 10);
  1804. if (WSNMP_FAILED(status)) {
  1805. SNMPDBG((
  1806. SNMP_LOG_ERROR,
  1807. "MGMTAPI: SnmpSetTimeout returned %d.\n",
  1808. SnmpGetLastError((HSNMP_SESSION)NULL)
  1809. ));
  1810. goto cleanup; // bail...
  1811. }
  1812. // attach retries specified with manager
  1813. status = SnmpSetRetry(pSMS->hManagerEntity, nRetries);
  1814. if (WSNMP_FAILED(status)) {
  1815. SNMPDBG((
  1816. SNMP_LOG_ERROR,
  1817. "MGMTAPI: SnmpSetRetry returned %d.\n",
  1818. SnmpGetLastError((HSNMP_SESSION)NULL)
  1819. ));
  1820. goto cleanup; // bail...
  1821. }
  1822. }
  1823. // validate pointer
  1824. if (pAgentCommunity != NULL) {
  1825. // transfer community string
  1826. smiCommunity.ptr = (smiLPBYTE)pAgentCommunity;
  1827. smiCommunity.len = pAgentCommunity ? lstrlen(pAgentCommunity) : 0;
  1828. // obtain context from community string
  1829. pSMS->hViewContext = SnmpStrToContext(
  1830. pSMS->hSnmpSession,
  1831. &smiCommunity
  1832. );
  1833. // validate context handle
  1834. if (WSNMP_FAILED(pSMS->hViewContext)) {
  1835. SNMPDBG((
  1836. SNMP_LOG_ERROR,
  1837. "MGMTAPI: SnmpStrToContext returned %d.\n",
  1838. SnmpGetLastError(pSMS->hSnmpSession)
  1839. ));
  1840. // re-initialize
  1841. pSMS->hViewContext = (HSNMP_CONTEXT)NULL;
  1842. goto cleanup; // bail...
  1843. }
  1844. }
  1845. // success
  1846. return TRUE;
  1847. cleanup:
  1848. // cleanup resources
  1849. CloseSession(pSMS);
  1850. // failure
  1851. return FALSE;
  1852. }
  1853. BOOL
  1854. AllocateSession(
  1855. PSNMP_MGR_SESSION * ppSMS
  1856. )
  1857. /*++
  1858. Routine Description:
  1859. Allocate mgmtapi session structure.
  1860. Arguments:
  1861. ppSMS - pointer to session pointer to return.
  1862. Return Values:
  1863. Returns true if successful.
  1864. --*/
  1865. {
  1866. PSNMP_MGR_SESSION pSMS = NULL;
  1867. __try
  1868. {
  1869. // allocate new session table entry
  1870. pSMS = SnmpUtilMemAlloc(sizeof(SNMP_MGR_SESSION));
  1871. // validate pointer
  1872. if (pSMS != NULL) {
  1873. // initialize session level lock
  1874. InitializeCriticalSection(&pSMS->SessionLock);
  1875. } else {
  1876. SNMPDBG((
  1877. SNMP_LOG_ERROR,
  1878. "MGMTAPI: Could not allocate session.\n"
  1879. ));
  1880. // notify application of error
  1881. SetLastError(SNMP_MEM_ALLOC_ERROR);
  1882. }
  1883. // transfer
  1884. *ppSMS = pSMS;
  1885. }
  1886. __except(EXCEPTION_EXECUTE_HANDLER)
  1887. {
  1888. if (pSMS != NULL)
  1889. {
  1890. SnmpUtilMemFree(pSMS);
  1891. pSMS = NULL;
  1892. }
  1893. }
  1894. // return status
  1895. return (pSMS != NULL);
  1896. }
  1897. VOID
  1898. FreeSession(
  1899. PSNMP_MGR_SESSION pSMS
  1900. )
  1901. /*++
  1902. Routine Description:
  1903. Frees mgmtapi session structure.
  1904. Arguments:
  1905. pSMS - pointer to mgmtapi session structure.
  1906. Return Values:
  1907. None.
  1908. --*/
  1909. {
  1910. // is session valid?
  1911. if (pSMS != NULL) {
  1912. // destroy the session level lock
  1913. DeleteCriticalSection(&pSMS->SessionLock);
  1914. // free session object
  1915. SnmpUtilMemFree(pSMS);
  1916. }
  1917. }
  1918. BOOL
  1919. ProcessAgentResponse(
  1920. PSNMP_MGR_SESSION pSMS
  1921. )
  1922. /*++
  1923. Routine Description:
  1924. Message pump for notification window.
  1925. Arguments:
  1926. pSMS - pointer to MGMTAPI session structure.
  1927. Return Values:
  1928. Returns true if agent responded.
  1929. --*/
  1930. {
  1931. MSG msg;
  1932. BOOL fOk = FALSE;
  1933. BOOL fRet;
  1934. // validate session ptr
  1935. WSNMP_ASSERT(pSMS != NULL);
  1936. // get the next message for this session
  1937. while ((fRet = GetMessage(&msg, pSMS->hWnd, 0, 0))) {
  1938. if (fRet == -1) {
  1939. // If there is an error, GetMessage returns -1
  1940. pSMS->nLastError = SNMPAPI_OTHER_ERROR;
  1941. SNMPDBG((
  1942. SNMP_LOG_ERROR,
  1943. "MGMTAPI: ProcessAgentResponse: GetMessage returns -1.\n"
  1944. ));
  1945. break;
  1946. }
  1947. // check for private message
  1948. if (msg.message != WM_WSNMP_DONE) {
  1949. // translate message
  1950. TranslateMessage(&msg);
  1951. // dispatch message
  1952. DispatchMessage(&msg);
  1953. } else {
  1954. // success
  1955. fOk = TRUE;
  1956. break;
  1957. }
  1958. }
  1959. return fOk;
  1960. }
  1961. DWORD
  1962. WINAPI
  1963. TrapThreadProc(
  1964. LPVOID lpParam
  1965. )
  1966. /*++
  1967. Routine Description:
  1968. Trap processing procedure.
  1969. Arguments:
  1970. lpParam - unused thread parameter.
  1971. Return Values:
  1972. Returns NOERROR if successful.
  1973. --*/
  1974. {
  1975. SNMPAPI_STATUS status;
  1976. PSNMP_MGR_SESSION pSMS;
  1977. SNMPDBG((
  1978. SNMP_LOG_TRACE,
  1979. "MGMTAPI: Trap thread starting...\n"
  1980. ));
  1981. // obtain pointer
  1982. pSMS = &g_TrapSMS;
  1983. // re-initialize
  1984. ZeroMemory(&g_TrapSMS, sizeof(g_TrapSMS));
  1985. g_fIsTrapRegistered = FALSE; // init to failure. Note that there will
  1986. // be only 1 instance of this thread
  1987. // initialize winsnmp trap session
  1988. if (OpenSession(pSMS, NULL, NULL, 0, 0))
  1989. {
  1990. // register
  1991. status = SnmpRegister(
  1992. pSMS->hSnmpSession,
  1993. (HSNMP_ENTITY)NULL, // hAgentEntity
  1994. (HSNMP_ENTITY)NULL, // hManagerEntity
  1995. (HSNMP_CONTEXT)NULL, // hViewContext
  1996. (smiLPCOID)NULL, // notification
  1997. SNMPAPI_ON
  1998. );
  1999. // validate return code
  2000. if (WSNMP_SUCCEEDED(status))
  2001. {
  2002. // signal main thread that Trap has been registered with WinSNMP
  2003. g_fIsTrapRegistered = TRUE;
  2004. SetEvent(g_hTrapRegisterdEvent);
  2005. // loop processing responses
  2006. while (ProcessAgentResponse(pSMS))
  2007. {
  2008. //
  2009. // processing done in window procedure...
  2010. //
  2011. }
  2012. }
  2013. else
  2014. {
  2015. SNMPDBG((
  2016. SNMP_LOG_ERROR,
  2017. "MGMTAPI: SnmpRegister returned %d.\n",
  2018. SnmpGetLastError(pSMS->hSnmpSession)
  2019. ));
  2020. // transfer last error to global structure
  2021. pSMS->nLastError = SnmpGetLastError(pSMS->hSnmpSession);
  2022. // signal main thread that there is an error
  2023. // in registering Trap with WinSNMP
  2024. SetEvent(g_hTrapRegisterdEvent);
  2025. }
  2026. }
  2027. else
  2028. {
  2029. // transfer last error to global structure
  2030. pSMS->nLastError = SnmpGetLastError((HSNMP_SESSION)NULL);
  2031. // signal main thread that there is an error
  2032. // in registering Trap with WinSNMP
  2033. SetEvent(g_hTrapRegisterdEvent);
  2034. goto ERROR_OUT;
  2035. }
  2036. if (g_fIsTrapRegistered)
  2037. {
  2038. // unregister WinSNMP notification reception
  2039. status = SnmpRegister(
  2040. pSMS->hSnmpSession,
  2041. (HSNMP_ENTITY)NULL, // hAgentEntity
  2042. (HSNMP_ENTITY)NULL, // hManagerEntity
  2043. (HSNMP_CONTEXT)NULL, // hViewContext
  2044. (smiLPCOID)NULL, // notification
  2045. SNMPAPI_OFF
  2046. );
  2047. // validate return code
  2048. if (WSNMP_FAILED(status))
  2049. {
  2050. SNMPDBG((
  2051. SNMP_LOG_ERROR,
  2052. "MGMTAPI: SnmpRegister SNMPAPI_OFF returned %d.\n",
  2053. SnmpGetLastError(pSMS->hSnmpSession)
  2054. ));
  2055. }
  2056. }
  2057. // free session
  2058. CloseSession(pSMS);
  2059. ERROR_OUT:
  2060. // obtain exclusive access
  2061. EnterCriticalSection(&g_GlobalLock);
  2062. // signal this thread has gone
  2063. g_fIsSnmpListening = FALSE;
  2064. // release exclusive access
  2065. LeaveCriticalSection(&g_GlobalLock);
  2066. SNMPDBG((
  2067. SNMP_LOG_TRACE,
  2068. "MGMTAPI: Trap thread exiting...\n"
  2069. ));
  2070. // success
  2071. return NOERROR;
  2072. }
  2073. BOOL
  2074. StartTrapsIfNecessary(
  2075. HANDLE * phTrapAvailable
  2076. )
  2077. /*++
  2078. Routine Description:
  2079. Initializes global structures for trap listening.
  2080. Arguments:
  2081. phTrapAvailable - pointer to event for signalling traps.
  2082. Return Values:
  2083. Returns true if successful (must be called only once).
  2084. --*/
  2085. {
  2086. BOOL fOk = FALSE;
  2087. DWORD dwTrapThreadId;
  2088. DWORD dwWaitTrapRegisterd;
  2089. // validate pointer
  2090. if (phTrapAvailable != NULL)
  2091. {
  2092. // obtain exclusive access
  2093. EnterCriticalSection(&g_GlobalLock);
  2094. // transfer trap event to app
  2095. *phTrapAvailable = g_hTrapEvent;
  2096. // only start listening once
  2097. if (g_fIsSnmpListening == FALSE)
  2098. {
  2099. // spawn client trap thread
  2100. g_hTrapThread = CreateThread(
  2101. NULL, // lpThreadAttributes
  2102. 0, // dwStackSize
  2103. TrapThreadProc,
  2104. NULL, // lpParameter
  2105. 0, // dwCreationFlags
  2106. &dwTrapThreadId
  2107. );
  2108. if (g_hTrapThread != NULL)
  2109. {
  2110. // signal successful start
  2111. g_fIsSnmpListening = TRUE;
  2112. // release exclusive access
  2113. LeaveCriticalSection(&g_GlobalLock);
  2114. // WinSE bug 6182
  2115. // wait for TrapThreadProc to signal sucessful or failure
  2116. dwWaitTrapRegisterd = WaitForSingleObject(g_hTrapRegisterdEvent, INFINITE);
  2117. if (dwWaitTrapRegisterd == WAIT_OBJECT_0)
  2118. {
  2119. if (g_fIsTrapRegistered == TRUE)
  2120. fOk = TRUE; // success
  2121. else
  2122. {
  2123. CloseHandle(g_hTrapThread);
  2124. g_hTrapThread = NULL;
  2125. SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
  2126. SNMPDBG((
  2127. SNMP_LOG_ERROR,
  2128. "MGMTAPI: Traps are not accessible.\n"
  2129. ));
  2130. }
  2131. }
  2132. else
  2133. {
  2134. CloseHandle(g_hTrapThread);
  2135. g_hTrapThread = NULL;
  2136. SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
  2137. SNMPDBG((
  2138. SNMP_LOG_ERROR,
  2139. "MGMTAPI: Traps are not accessible.\n"
  2140. ));
  2141. }
  2142. // In case where fOk == TRUE, g_hTrapThread will be closed when
  2143. // - new app calls SnmpMgrClose(NULL)
  2144. // OR
  2145. // - DLL_PROCESS_DETACH in DllMain is called for legacy app.
  2146. }
  2147. else
  2148. {
  2149. // release exclusive access
  2150. LeaveCriticalSection(&g_GlobalLock);
  2151. SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
  2152. SNMPDBG((
  2153. SNMP_LOG_ERROR,
  2154. "MGMTAPI: CreateThread TrapThreadProc failed %d.\n",
  2155. GetLastError()
  2156. ));
  2157. }
  2158. }
  2159. else
  2160. {
  2161. // whine about having called this before
  2162. SetLastError(SNMP_MGMTAPI_TRAP_DUPINIT);
  2163. SNMPDBG((
  2164. SNMP_LOG_ERROR,
  2165. "MGMTAPI: Duplicate registration detected.\n"
  2166. ));
  2167. // release exclusive access
  2168. LeaveCriticalSection(&g_GlobalLock);
  2169. }
  2170. }
  2171. return fOk;
  2172. }
  2173. ///////////////////////////////////////////////////////////////////////////////
  2174. // //
  2175. // Dll Entry Point //
  2176. // //
  2177. ///////////////////////////////////////////////////////////////////////////////
  2178. BOOL
  2179. DllMain(
  2180. HANDLE hDll,
  2181. DWORD dwReason,
  2182. LPVOID lpReserved
  2183. )
  2184. /*++
  2185. Routine Description:
  2186. Dll entry point.
  2187. Arguments:
  2188. hDll - module handle.
  2189. dwReason - reason DllMain is being called.
  2190. lpReserved - unused.
  2191. Return Values:
  2192. None.
  2193. --*/
  2194. {
  2195. BOOL bOk = TRUE;
  2196. __try
  2197. {
  2198. // determine reason for being called
  2199. if (dwReason == DLL_PROCESS_ATTACH)
  2200. {
  2201. // initialize startup critical section
  2202. InitializeCriticalSection(&g_GlobalLock);
  2203. // initialize list of incoming traps
  2204. InitializeListHead(&g_IncomingTraps);
  2205. // optimize thread startup
  2206. DisableThreadLibraryCalls(hDll);
  2207. // save handle
  2208. g_hDll = hDll;
  2209. }
  2210. else if (dwReason == DLL_PROCESS_DETACH)
  2211. {
  2212. if (g_hTrapThread)
  2213. {
  2214. CloseHandle(g_hTrapThread);
  2215. }
  2216. // cleanup winsnmp
  2217. CleanupIfNecessary();
  2218. // nuke startup critical section
  2219. DeleteCriticalSection(&g_GlobalLock);
  2220. }
  2221. }
  2222. __except(EXCEPTION_EXECUTE_HANDLER)
  2223. {
  2224. bOk = FALSE;
  2225. }
  2226. return bOk;
  2227. }
  2228. ///////////////////////////////////////////////////////////////////////////////
  2229. // //
  2230. // Public Procedures //
  2231. // //
  2232. ///////////////////////////////////////////////////////////////////////////////
  2233. LPSNMP_MGR_SESSION
  2234. SNMP_FUNC_TYPE
  2235. SnmpMgrOpen(
  2236. LPSTR pAgentAddress,
  2237. LPSTR pAgentCommunity,
  2238. INT nTimeOut,
  2239. INT nRetries
  2240. )
  2241. /*++
  2242. Routine Description:
  2243. Initializes resources necessary for communication with specified agent.
  2244. Arguments:
  2245. pAgentAddress - points to a null-terminated string specifying either a
  2246. dotted-decimal IP address or a host name that can be resolved to an
  2247. IP address, an IPX address (in 8.12 notation), or an ethernet address.
  2248. pAgentCommunity - points to a null-terminated string specifying the
  2249. SNMP community name used when communicating with the agent specified
  2250. in the lpAgentAddress parameter
  2251. nTimeOut - specifies the communications time-out in milliseconds.
  2252. nRetries - specifies the communications retry count.
  2253. Return Values:
  2254. Returns session handle if successful.
  2255. --*/
  2256. {
  2257. PSNMP_MGR_SESSION pSMS = NULL;
  2258. // initialize winsnmp
  2259. if (StartSnmpIfNecessary()) {
  2260. // allocate mgmtapi session
  2261. if (AllocateSession(&pSMS)) {
  2262. // open session
  2263. if (!OpenSession(
  2264. pSMS,
  2265. pAgentAddress,
  2266. pAgentCommunity,
  2267. nTimeOut,
  2268. nRetries)) {
  2269. // free session
  2270. FreeSession(pSMS);
  2271. // reset
  2272. pSMS = NULL;
  2273. }
  2274. else
  2275. {
  2276. // add ref
  2277. AddMgmtRef();
  2278. }
  2279. }
  2280. }
  2281. // return opaque pointer
  2282. return (LPSNMP_MGR_SESSION)pSMS;
  2283. }
  2284. BOOL
  2285. SNMP_FUNC_TYPE
  2286. SnmpMgrCtl(
  2287. LPSNMP_MGR_SESSION session, // pointer to the MGMTAPI session
  2288. DWORD dwCtlCode, // control code for the command requested
  2289. LPVOID lpvInBuffer, // buffer with the input parameters for the operation
  2290. DWORD cbInBuffer, // size of lpvInBuffer in bytes
  2291. LPVOID lpvOUTBuffer, // buffer for all the output parameters of the command
  2292. DWORD cbOUTBuffer, // size of lpvOUTBuffer
  2293. LPDWORD lpcbBytesReturned // space used from lpvOutBuffer
  2294. )
  2295. /*++
  2296. Routine Description:
  2297. Operates several control operations over the MGMTAPI session
  2298. Arguments:
  2299. pSession - pointer to the session to
  2300. Return Values:
  2301. --*/
  2302. {
  2303. BOOL bOk = FALSE;
  2304. PSNMP_MGR_SESSION pSMS = (PSNMP_MGR_SESSION)session;
  2305. switch(dwCtlCode)
  2306. {
  2307. case MGMCTL_SETAGENTPORT:
  2308. if (pSMS == NULL)
  2309. SetLastError(SNMP_MGMTAPI_INVALID_SESSION);
  2310. else if (lpvInBuffer == NULL || cbInBuffer < sizeof(UINT))
  2311. SetLastError(SNMP_MGMTAPI_INVALID_BUFFER);
  2312. else if (WSNMP_FAILED(SnmpSetPort(pSMS->hAgentEntity, *(UINT*)lpvInBuffer)))
  2313. SetLastError(SnmpGetLastError(pSMS->hSnmpSession));
  2314. else
  2315. bOk = TRUE;
  2316. break;
  2317. default:
  2318. SetLastError(SNMP_MGMTAPI_INVALID_CTL);
  2319. break;
  2320. }
  2321. return bOk;
  2322. }
  2323. BOOL
  2324. SNMP_FUNC_TYPE
  2325. SnmpMgrClose(
  2326. LPSNMP_MGR_SESSION session
  2327. )
  2328. /*++
  2329. Routine Description:
  2330. Cleanups resources needed for communication with specified agent.
  2331. Arguments:
  2332. session - points to an internal structure that specifies
  2333. which session to close.
  2334. Return Values:
  2335. Returns true if successful.
  2336. Notes:
  2337. BUG: 585652
  2338. -Cleanup WinSNMP resources if reference count on using mgmtapi.dll reaches 0
  2339. -SnmpMgrClose(NULL) is used to cleanup resources created by SnmpMgrTrapListen
  2340. --*/
  2341. {
  2342. BOOL fOk = TRUE;
  2343. DWORD dwWaitResult;
  2344. PSNMP_MGR_SESSION pSMS = (PSNMP_MGR_SESSION)session;
  2345. // validate pointer
  2346. if (pSMS != NULL) {
  2347. // close session
  2348. CloseSession(pSMS);
  2349. // free session
  2350. FreeSession(pSMS);
  2351. // release ref
  2352. ReleaseMgmtRef();
  2353. }
  2354. else if (g_fIsSnmpListening && g_TrapSMS.hWnd && g_hTrapThread)
  2355. {
  2356. if (PostMessage(g_TrapSMS.hWnd, WM_QUIT, (WPARAM)0, (LPARAM)0))
  2357. {
  2358. // block until TrapThreadProc has gone
  2359. dwWaitResult = WaitForSingleObject(g_hTrapThread, INFINITE);
  2360. switch (dwWaitResult)
  2361. {
  2362. case WAIT_OBJECT_0 :
  2363. SNMPDBG((
  2364. SNMP_LOG_TRACE,
  2365. "MGMTAPI: SnmpMgrClose: TrapThreadProc exited.\n"
  2366. ));
  2367. break;
  2368. case WAIT_FAILED:
  2369. SNMPDBG((
  2370. SNMP_LOG_ERROR,
  2371. "MGMTAPI: SnmpMgrClose: WaitForSingleObject returned WAIT_FAILED %u.\n",
  2372. GetLastError()
  2373. ));
  2374. break;
  2375. default :
  2376. SNMPDBG((
  2377. SNMP_LOG_ERROR,
  2378. "MGMTAPI: SnmpMgrClose: WaitForSingleObject returned %u.\n",
  2379. dwWaitResult
  2380. ));
  2381. break;
  2382. }
  2383. }
  2384. else
  2385. {
  2386. fOk = FALSE;
  2387. SNMPDBG((
  2388. SNMP_LOG_ERROR,
  2389. "MGMTAPI: SnmpMgrClose: PostMessage returned %u.\n",
  2390. GetLastError()
  2391. ));
  2392. }
  2393. if (! CloseHandle(g_hTrapThread))
  2394. {
  2395. SNMPDBG((
  2396. SNMP_LOG_ERROR,
  2397. "MGMTAPI: SnmpMgrClose: CloseHandle on %u returned %u.\n",
  2398. g_hTrapThread, GetLastError()
  2399. ));
  2400. }
  2401. g_hTrapThread = NULL;
  2402. // release ref
  2403. ReleaseMgmtRef();
  2404. }
  2405. return fOk;
  2406. }
  2407. SNMPAPI
  2408. SNMP_FUNC_TYPE
  2409. SnmpMgrRequest(
  2410. LPSNMP_MGR_SESSION session,
  2411. BYTE requestType,
  2412. SnmpVarBindList * pVarBindList,
  2413. AsnInteger * pErrorStatus,
  2414. AsnInteger * pErrorIndex
  2415. )
  2416. /*++
  2417. Routine Description:
  2418. Requests the specified operation be performed with the specified agent.
  2419. Arguments:
  2420. session - points to an internal structure that specifies the session
  2421. that will perform the request.
  2422. requestType - specifies the SNMP request type.
  2423. pVarBindList - points to the variable bindings list
  2424. pErrorStatus - points to a variable in which the error status result
  2425. will be returned.
  2426. pErrorIndex - points to a variable in which the error index result
  2427. will be returned.
  2428. Return Values:
  2429. Returns true if successful.
  2430. --*/
  2431. {
  2432. BOOL fOk = FALSE;
  2433. SNMPAPI_STATUS status;
  2434. PSNMP_MGR_SESSION pSMS = (PSNMP_MGR_SESSION)session;
  2435. // validate pointers
  2436. if ((pSMS != NULL) &&
  2437. (pErrorIndex != NULL) &&
  2438. (pErrorStatus != NULL) &&
  2439. (pVarBindList != NULL) &&
  2440. (pVarBindList->len != 0) &&
  2441. (pVarBindList->list != NULL)) {
  2442. // obtain exclusive access to session
  2443. EnterCriticalSection(&pSMS->SessionLock);
  2444. // initialize session structure
  2445. pSMS->pVarBindList = pVarBindList;
  2446. pSMS->nPduType = (smiINT32)(BYTE)requestType;
  2447. pSMS->hVbl = (HSNMP_VBL)NULL;
  2448. pSMS->hPdu = (HSNMP_PDU)NULL;
  2449. pSMS->nErrorStatus = 0;
  2450. pSMS->nErrorIndex = 0;
  2451. pSMS->nLastError = 0;
  2452. // allocate resources
  2453. if (AllocatePdu(pSMS)) {
  2454. // actually send
  2455. status = SnmpSendMsg(
  2456. pSMS->hSnmpSession,
  2457. pSMS->hManagerEntity,
  2458. pSMS->hAgentEntity,
  2459. pSMS->hViewContext,
  2460. pSMS->hPdu
  2461. );
  2462. // release now
  2463. FreePdu(pSMS);
  2464. // validate return code
  2465. if (WSNMP_SUCCEEDED(status)) {
  2466. // process agent response
  2467. if (ProcessAgentResponse(pSMS) &&
  2468. (pSMS->nLastError == SNMP_ERROR_NOERROR)) {
  2469. // update error status and index
  2470. *pErrorStatus = pSMS->nErrorStatus;
  2471. *pErrorIndex = pSMS->nErrorIndex;
  2472. // success
  2473. fOk = TRUE;
  2474. } else {
  2475. // set error to winsnmp error
  2476. SetLastError(pSMS->nLastError);
  2477. // failure
  2478. fOk = FALSE;
  2479. }
  2480. } else {
  2481. SNMPDBG((
  2482. SNMP_LOG_ERROR,
  2483. "MGMTAPI: SnmpSendMsg returned %d.\n",
  2484. SnmpGetLastError(pSMS->hSnmpSession)
  2485. ));
  2486. }
  2487. }
  2488. // release exclusive access to session
  2489. LeaveCriticalSection(&pSMS->SessionLock);
  2490. }
  2491. return fOk;
  2492. }
  2493. BOOL
  2494. SNMP_FUNC_TYPE
  2495. SnmpMgrStrToOid(
  2496. LPSTR pString,
  2497. AsnObjectIdentifier * pOID
  2498. )
  2499. /*++
  2500. Routine Description:
  2501. Converts a string object identifier or object descriptor representation
  2502. to an internal object identifier.
  2503. Arguments:
  2504. pString - points to a null-terminated string to be converted.
  2505. pOID - points to an object identifier variable that will receive the
  2506. converted value.
  2507. Return Values:
  2508. Returns true if successful.
  2509. --*/
  2510. {
  2511. // validate pointer to oid and string
  2512. if ((pOID != NULL) && (pString != NULL)) {
  2513. // forward to mibcc code for now
  2514. return SnmpMgrText2Oid(pString, pOID);
  2515. }
  2516. return FALSE;
  2517. }
  2518. BOOL
  2519. SNMP_FUNC_TYPE
  2520. SnmpMgrOidToStr(
  2521. AsnObjectIdentifier * pOID,
  2522. LPSTR * ppString
  2523. )
  2524. /*++
  2525. Routine Description:
  2526. Converts an internal object identifier to a string object identifier or
  2527. object descriptor representation.
  2528. Arguments:
  2529. pOID - pointers to object identifier to be converted.
  2530. ppString - points to string pointer to receive converted value.
  2531. Return Values:
  2532. Returns true if successful.
  2533. --*/
  2534. {
  2535. // validate pointer to oid and string
  2536. if ((pOID != NULL) && (ppString != NULL)) {
  2537. // forward to mibcc code for now
  2538. return SnmpMgrOid2Text(pOID, ppString);
  2539. }
  2540. return FALSE;
  2541. }
  2542. BOOL
  2543. SNMP_FUNC_TYPE
  2544. SnmpMgrTrapListen(
  2545. HANDLE * phTrapAvailable
  2546. )
  2547. /*++
  2548. Routine Description:
  2549. Registers the ability of a manager application to receive SNMP traps.
  2550. Arguments:
  2551. phTrapAvailable - points to an event handle that will be used to indicate
  2552. that there are traps available
  2553. Return Values:
  2554. Returns true if successful.
  2555. --*/
  2556. {
  2557. BOOL fOk = FALSE;
  2558. // startup winsnmp
  2559. if (StartSnmpIfNecessary()) {
  2560. // spawn only one trap client thread
  2561. if (StartTrapsIfNecessary(phTrapAvailable)) {
  2562. // success
  2563. fOk = TRUE;
  2564. // add ref
  2565. AddMgmtRef();
  2566. }
  2567. }
  2568. return fOk;
  2569. }
  2570. BOOL
  2571. SNMP_FUNC_TYPE
  2572. SnmpMgrGetTrap(
  2573. AsnObjectIdentifier * pEnterpriseOID,
  2574. AsnNetworkAddress * pAgentAddress,
  2575. AsnInteger * pGenericTrap,
  2576. AsnInteger * pSpecificTrap,
  2577. AsnTimeticks * pTimeStamp,
  2578. SnmpVarBindList * pVarBindList
  2579. )
  2580. /*++
  2581. Routine Description:
  2582. Returns outstanding trap data that the caller has not received if
  2583. trap reception is enabled.
  2584. Arguments:
  2585. pEnterpriseOID - points to an object identifier that specifies the
  2586. enterprise that generated the SNMP trap
  2587. pAgentAddress - points to the address of the agent that generated the
  2588. SNMP trap (retrieved from PDU).
  2589. pGenericTrap - points to an indicator of the generic trap id.
  2590. pSpecificTrap - points to an indicator of the specific trap id.
  2591. pTimeStamp - points to a variable to receive the time stamp.
  2592. pVarBindList - points to the associated variable bindings.
  2593. Return Values:
  2594. Returns true if successful.
  2595. --*/
  2596. {
  2597. // forward to new api
  2598. return SnmpMgrGetTrapEx(
  2599. pEnterpriseOID,
  2600. pAgentAddress,
  2601. NULL,
  2602. pGenericTrap,
  2603. pSpecificTrap,
  2604. NULL,
  2605. pTimeStamp,
  2606. pVarBindList
  2607. );
  2608. }
  2609. BOOL
  2610. SNMP_FUNC_TYPE
  2611. SnmpMgrGetTrapEx(
  2612. AsnObjectIdentifier * pEnterpriseOID,
  2613. AsnNetworkAddress * pAgentAddress,
  2614. AsnNetworkAddress * pSourceAddress,
  2615. AsnInteger * pGenericTrap,
  2616. AsnInteger * pSpecificTrap,
  2617. AsnOctetString * pCommunity,
  2618. AsnTimeticks * pTimeStamp,
  2619. SnmpVarBindList * pVarBindList
  2620. )
  2621. /*++
  2622. Routine Description:
  2623. Returns outstanding trap data that the caller has not received if
  2624. trap reception is enabled.
  2625. Arguments:
  2626. pEnterpriseOID - points to an object identifier that specifies the
  2627. enterprise that generated the SNMP trap
  2628. pAgentAddress - points to the address of the agent that generated the
  2629. SNMP trap (retrieved from PDU).
  2630. pSourceAddress - points to the address of the agent that generated the
  2631. SNMP trap (retrieved from network transport).
  2632. pGenericTrap - points to an indicator of the generic trap id.
  2633. pSpecificTrap - points to an indicator of the specific trap id.
  2634. pCommunity - points to structure to receive community string.
  2635. pTimeStamp - points to a variable to receive the time stamp.
  2636. pVarBindList - points to the associated variable bindings.
  2637. Return Values:
  2638. Returns true if successful.
  2639. --*/
  2640. {
  2641. BOOL fOk = FALSE;
  2642. PLIST_ENTRY pLE = NULL;
  2643. PTRAP_LIST_ENTRY pTLE = NULL;
  2644. smiINT32 nLastError;
  2645. // obtain exclusive access
  2646. EnterCriticalSection(&g_GlobalLock);
  2647. // make sure list has entries
  2648. if (!IsListEmpty(&g_IncomingTraps)) {
  2649. // remove first item from list
  2650. pLE = RemoveHeadList(&g_IncomingTraps);
  2651. } else {
  2652. // check for trap thread failure
  2653. nLastError = g_TrapSMS.nLastError;
  2654. }
  2655. // release exclusive access
  2656. LeaveCriticalSection(&g_GlobalLock);
  2657. // validate pointer
  2658. if (pLE != NULL) {
  2659. // retrieve pointer to trap list entry
  2660. pTLE = CONTAINING_RECORD(pLE, TRAP_LIST_ENTRY, Link);
  2661. // validate pointer
  2662. if (pEnterpriseOID != NULL) {
  2663. // manually copy enterprise oid
  2664. *pEnterpriseOID = pTLE->EnterpriseOID;
  2665. // re-initialize list entry
  2666. pTLE->EnterpriseOID.ids = NULL;
  2667. pTLE->EnterpriseOID.idLength = 0;
  2668. }
  2669. // validate pointer
  2670. if (pCommunity != NULL) {
  2671. // transfer string info
  2672. *pCommunity = pTLE->Community;
  2673. // re-initialize list entry
  2674. pTLE->Community.length = 0;
  2675. pTLE->Community.stream = NULL;
  2676. pTLE->Community.dynamic = FALSE;
  2677. }
  2678. // validate pointer
  2679. if (pVarBindList != NULL) {
  2680. // transfer varbindlist
  2681. *pVarBindList = pTLE->VarBindList;
  2682. // re-initialize list entry
  2683. pTLE->VarBindList.len = 0;
  2684. pTLE->VarBindList.list = NULL;
  2685. }
  2686. // validate pointer
  2687. if (pAgentAddress != NULL) {
  2688. // copy structure
  2689. *pAgentAddress = pTLE->AgentAddress;
  2690. // remove our reference
  2691. pTLE->AgentAddress.length = 0;
  2692. pTLE->AgentAddress.stream = NULL;
  2693. pTLE->AgentAddress.dynamic = FALSE;
  2694. }
  2695. // validate pointer
  2696. if (pSourceAddress != NULL) {
  2697. // copy structure
  2698. *pSourceAddress = pTLE->SourceAddress;
  2699. // remove our reference
  2700. pTLE->SourceAddress.length = 0;
  2701. pTLE->SourceAddress.stream = NULL;
  2702. pTLE->SourceAddress.dynamic = FALSE;
  2703. }
  2704. // validate pointer
  2705. if (pGenericTrap != NULL) {
  2706. // transfer generic trap info
  2707. *pGenericTrap = pTLE->nGenericTrap;
  2708. }
  2709. // validate pointer
  2710. if (pSpecificTrap != NULL) {
  2711. // transfer generic trap info
  2712. *pSpecificTrap = pTLE->nSpecificTrap;
  2713. }
  2714. // validate pointer
  2715. if (pTimeStamp != NULL) {
  2716. // transfer time info
  2717. *pTimeStamp = pTLE->TimeStamp;
  2718. }
  2719. // release
  2720. FreeTle(pTLE);
  2721. // success
  2722. fOk = TRUE;
  2723. } else if (nLastError != NOERROR) {
  2724. // indicate there was an thread error
  2725. SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
  2726. } else {
  2727. // indicate there are no traps
  2728. SetLastError(SNMP_MGMTAPI_NOTRAPS);
  2729. }
  2730. return fOk;
  2731. }