Source code of Windows XP (NT5)
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.

904 lines
19 KiB

  1. /*++
  2. Copyright (c) 1992-1997 Microsoft Corporation
  3. Module Name:
  4. subagnts.c
  5. Abstract:
  6. Contains definitions for manipulating subagent structures.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 10-Feb-1997 DonRyan
  11. Rewrote to implement SNMPv2 support.
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include "globals.h"
  19. #include "subagnts.h"
  20. #include "regions.h"
  21. #include "snmpmgmt.h"
  22. ///////////////////////////////////////////////////////////////////////////////
  23. // //
  24. // Private procedures //
  25. // //
  26. ///////////////////////////////////////////////////////////////////////////////
  27. BOOL
  28. FindSubagent(
  29. PSUBAGENT_LIST_ENTRY * ppSLE,
  30. LPSTR pPathname
  31. )
  32. /*++
  33. Routine Description:
  34. Locates subagent in list.
  35. Arguments:
  36. ppSLE - pointer to receive pointer to entry.
  37. pPathname - pointer to pathname to find.
  38. Return Values:
  39. Returns true if successful.
  40. --*/
  41. {
  42. PLIST_ENTRY pLE;
  43. PSUBAGENT_LIST_ENTRY pSLE;
  44. // initialize
  45. *ppSLE = NULL;
  46. // obtain pointer to head
  47. pLE = g_Subagents.Flink;
  48. // process all entries in list
  49. while (pLE != &g_Subagents) {
  50. // retrieve pointer to trap destination structure
  51. pSLE = CONTAINING_RECORD(pLE, SUBAGENT_LIST_ENTRY, Link);
  52. // compare pathname string with entry
  53. if (!strcmp(pSLE->pPathname, pPathname)) {
  54. // transfer
  55. *ppSLE = pSLE;
  56. // success
  57. return TRUE;
  58. }
  59. // next entry
  60. pLE = pLE->Flink;
  61. }
  62. // failure
  63. return FALSE;
  64. }
  65. BOOL
  66. AddSubagentRegion(
  67. PSUBAGENT_LIST_ENTRY pSLE,
  68. AsnObjectIdentifier * pPrefixOid
  69. )
  70. /*++
  71. Routine Description:
  72. Adds subagent supported region to structure.
  73. Arguments:
  74. pSLE - pointer to subagent structure.
  75. pPrefixOid - pointer to supported region.
  76. Return Values:
  77. Returns true if successful.
  78. --*/
  79. {
  80. BOOL fOk = FALSE;
  81. PMIB_REGION_LIST_ENTRY pRLE = NULL;
  82. // allocate region
  83. if (AllocRLE(&pRLE)) {
  84. // save pointer
  85. pRLE->pSLE = pSLE;
  86. // copy prefix to structure
  87. SnmpUtilOidCpy(&pRLE->PrefixOid, pPrefixOid);
  88. // copy prefix as temporary limit
  89. SnmpUtilOidCpy(&pRLE->LimitOid, pPrefixOid);
  90. // modify limit oid to be one past the prefix
  91. ++pRLE->LimitOid.ids[pRLE->LimitOid.idLength - 1];
  92. SNMPDBG((
  93. SNMP_LOG_TRACE,
  94. "SNMP: SVC: %s supports %s.\n",
  95. pSLE->pPathname,
  96. SnmpUtilOidToA(&pRLE->PrefixOid)
  97. ));
  98. // attach to mib region to subagent structure
  99. InsertTailList(&pSLE->SupportedRegions, &pRLE->Link);
  100. // success
  101. fOk = TRUE;
  102. }
  103. return fOk;
  104. }
  105. BOOL
  106. OfferInternalMgmtVariables(
  107. PSUBAGENT_LIST_ENTRY pSLE
  108. )
  109. /*++
  110. Routine Description:
  111. if the subagent is willing to monitor the SNMP service
  112. this function is offering it a pointer to the internal
  113. management variables
  114. Arguments:
  115. pSLE - pointer to subagent structure.
  116. Return Values:
  117. Returns true anyway.
  118. --*/
  119. {
  120. if (pSLE->pfnSnmpExtensionMonitor != NULL)
  121. {
  122. __try {
  123. // attempt to initialize agent
  124. (*pSLE->pfnSnmpExtensionMonitor)(&snmpMgmtBase);
  125. } __except (EXCEPTION_EXECUTE_HANDLER) {
  126. SNMPDBG((
  127. SNMP_LOG_ERROR,
  128. "SNMP: SVC: exception 0x%08lx offering internals to %s.\n",
  129. GetExceptionCode(),
  130. pSLE->pPathname
  131. ));
  132. // failure
  133. return FALSE;
  134. }
  135. }
  136. return TRUE;
  137. }
  138. BOOL
  139. LoadSubagentRegions(
  140. PSUBAGENT_LIST_ENTRY pSLE
  141. )
  142. /*++
  143. Routine Description:
  144. Loads subagent supported regions.
  145. Arguments:
  146. pSLE - pointer to subagent structure.
  147. Return Values:
  148. Returns true if successful.
  149. --*/
  150. {
  151. BOOL fOk = FALSE;
  152. HANDLE hSubagentTrapEvent = NULL;
  153. AsnObjectIdentifier PrefixOid = { 0, NULL };
  154. __try {
  155. // attempt to initialize agent
  156. if ((*pSLE->pfnSnmpExtensionInit)(
  157. g_dwUpTimeReference,
  158. &hSubagentTrapEvent,
  159. &PrefixOid
  160. )) {
  161. // store subagent trap event handle
  162. pSLE->hSubagentTrapEvent = hSubagentTrapEvent;
  163. // add subagent region to list entry
  164. fOk = AddSubagentRegion(pSLE, &PrefixOid);
  165. // check to see if subagent supports additional regions
  166. if (fOk && (pSLE->pfnSnmpExtensionInitEx != NULL)) {
  167. BOOL fMoreRegions = TRUE;
  168. // get other regions
  169. while (fOk && fMoreRegions) {
  170. // retrieve next supported region
  171. fMoreRegions = (*pSLE->pfnSnmpExtensionInitEx)(
  172. &PrefixOid
  173. );
  174. // validate
  175. if (fMoreRegions) {
  176. // add subagent region to list entry
  177. fOk = AddSubagentRegion(pSLE, &PrefixOid);
  178. }
  179. }
  180. }
  181. }
  182. } __except (EXCEPTION_EXECUTE_HANDLER) {
  183. SNMPDBG((
  184. SNMP_LOG_ERROR,
  185. "SNMP: SVC: exception 0x%08lx loading %s.\n",
  186. GetExceptionCode(),
  187. pSLE->pPathname
  188. ));
  189. // failure
  190. fOk = FALSE;
  191. }
  192. return fOk;
  193. }
  194. BOOL
  195. LoadSubagent(
  196. PSUBAGENT_LIST_ENTRY pSLE
  197. )
  198. /*++
  199. Routine Description:
  200. Loads subagent dll and initializes.
  201. Arguments:
  202. pSLE - pointer to subagent structure.
  203. Return Values:
  204. Returns true if successful.
  205. --*/
  206. {
  207. BOOL fOk = FALSE;
  208. // attempt to load subagent library - we use the altered search path flag so that
  209. // the subagent can load DLLs that live in its directory
  210. pSLE->hSubagentDll = LoadLibraryExA(pSLE->pPathname, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
  211. // validate handle
  212. if (pSLE->hSubagentDll != NULL) {
  213. // load primary initialization routine
  214. pSLE->pfnSnmpExtensionInit = (PFNSNMPEXTENSIONINIT)
  215. GetProcAddress(
  216. pSLE->hSubagentDll,
  217. SNMP_EXTENSION_INIT
  218. );
  219. // load secondary initialization routine
  220. pSLE->pfnSnmpExtensionInitEx = (PFNSNMPEXTENSIONINITEX)
  221. GetProcAddress(
  222. pSLE->hSubagentDll,
  223. SNMP_EXTENSION_INIT_EX
  224. );
  225. // load secondary initialization routine
  226. pSLE->pfnSnmpExtensionClose = (PFNSNMPEXTENSIONCLOSE)
  227. GetProcAddress(
  228. pSLE->hSubagentDll,
  229. SNMP_EXTENSION_CLOSE
  230. );
  231. // load the extension monitor routine
  232. pSLE->pfnSnmpExtensionMonitor = (PFNSNMPEXTENSIONMONITOR)
  233. GetProcAddress(
  234. pSLE->hSubagentDll,
  235. SNMP_EXTENSION_MONITOR
  236. );
  237. // load snmpv1-based subagent request routine
  238. pSLE->pfnSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY)
  239. GetProcAddress(
  240. pSLE->hSubagentDll,
  241. SNMP_EXTENSION_QUERY
  242. );
  243. // load snmpv2-based subagent request routine
  244. pSLE->pfnSnmpExtensionQueryEx = (PFNSNMPEXTENSIONQUERYEX)
  245. GetProcAddress(
  246. pSLE->hSubagentDll,
  247. SNMP_EXTENSION_QUERY_EX
  248. );
  249. // load snmpv1-based subagent trap routine
  250. pSLE->pfnSnmpExtensionTrap = (PFNSNMPEXTENSIONTRAP)
  251. GetProcAddress(
  252. pSLE->hSubagentDll,
  253. SNMP_EXTENSION_TRAP
  254. );
  255. // validate subagent agent entry points
  256. if ((pSLE->pfnSnmpExtensionInit != NULL) &&
  257. ((pSLE->pfnSnmpExtensionQuery != NULL) ||
  258. (pSLE->pfnSnmpExtensionQueryEx != NULL))) {
  259. // load supported regions
  260. if (fOk = LoadSubagentRegions(pSLE)) // !!intentional assignement!!
  261. {
  262. // offering internal management variables;
  263. fOk = OfferInternalMgmtVariables(pSLE);
  264. }
  265. }
  266. }
  267. else
  268. {
  269. DWORD errCode = GetLastError();
  270. LPTSTR pPathname;
  271. #ifdef UNICODE
  272. SnmpUtilUTF8ToUnicode(&pPathname, pSLE->pPathname, TRUE);
  273. #else
  274. pPathname = pSLE->pPathname;
  275. #endif
  276. SNMPDBG((
  277. SNMP_LOG_ERROR,
  278. "SNMP: SVC: error %d loading subagent.\n",
  279. errCode
  280. ));
  281. ReportSnmpEvent(
  282. SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL,
  283. 1,
  284. &pPathname,
  285. errCode);
  286. #ifdef UNICODE
  287. SnmpUtilMemFree(pPathname);
  288. #endif
  289. }
  290. return fOk;
  291. }
  292. BOOL
  293. AddSubagentByDll(
  294. LPSTR pPathname,
  295. UCHAR uchInitFlags
  296. )
  297. /*++
  298. Routine Description:
  299. Adds subagent to list.
  300. Arguments:
  301. pPathname - pointer to subagent's dll path.
  302. Return Values:
  303. Returns true if successful.
  304. --*/
  305. {
  306. BOOL fOk = FALSE;
  307. PSUBAGENT_LIST_ENTRY pSLE = NULL;
  308. // attempt to locate in list
  309. if (FindSubagent(&pSLE, pPathname)) {
  310. SNMPDBG((
  311. SNMP_LOG_WARNING,
  312. "SNMP: SVC: duplicate entry for %s.\n",
  313. pPathname
  314. ));
  315. // success
  316. fOk = TRUE;
  317. } else {
  318. // allocate subagent structure
  319. if (AllocSLE(&pSLE, pPathname, uchInitFlags)) {
  320. SNMPDBG((
  321. SNMP_LOG_TRACE,
  322. "SNMP: SVC: processing subagent %s.\n",
  323. pPathname
  324. ));
  325. // initialize subagent
  326. if (LoadSubagent(pSLE)) {
  327. // insert into valid communities list
  328. InsertTailList(&g_Subagents, &pSLE->Link);
  329. // success
  330. fOk = TRUE;
  331. }
  332. // cleanup
  333. if (!fOk) {
  334. // release
  335. FreeSLE(pSLE);
  336. }
  337. }
  338. }
  339. return fOk;
  340. }
  341. BOOL
  342. AddSubagentByKey(
  343. LPTSTR pKey
  344. )
  345. /*++
  346. Routine Description:
  347. Adds subagent to list.
  348. Arguments:
  349. pKey - pointer to subagent's registry key path.
  350. Return Values:
  351. Returns true if successful.
  352. --*/
  353. {
  354. HKEY hKey;
  355. LONG lStatus;
  356. DWORD dwIndex;
  357. DWORD dwNameSize;
  358. DWORD dwValueSize;
  359. DWORD dwValueType;
  360. CHAR szName[MAX_PATH];
  361. CHAR szValue[MAX_PATH];
  362. BOOL fOk = FALSE;
  363. PSUBAGENT_LIST_ENTRY pSLE = NULL;
  364. // open registry subkey
  365. lStatus = RegOpenKeyEx(
  366. HKEY_LOCAL_MACHINE,
  367. pKey,
  368. 0,
  369. KEY_READ,
  370. &hKey
  371. );
  372. // validate return code
  373. if (lStatus == ERROR_SUCCESS) {
  374. // initialize
  375. dwIndex = 0;
  376. // initialize buffer sizes
  377. dwNameSize = sizeof(szName);
  378. dwValueSize = sizeof(szValue);
  379. // loop until error or end of list
  380. while (lStatus == ERROR_SUCCESS) {
  381. // read next value
  382. lStatus = RegEnumValueA(
  383. hKey,
  384. dwIndex,
  385. szName,
  386. &dwNameSize,
  387. NULL,
  388. &dwValueType,
  389. szValue,
  390. &dwValueSize
  391. );
  392. // validate return code
  393. if (lStatus == ERROR_SUCCESS) {
  394. // check to see if value is pathname
  395. if (!_stricmp(szName, REG_VALUE_SUBAGENT_PATH)) {
  396. DWORD dwRequired;
  397. CHAR szExpanded[MAX_PATH];
  398. // expand environment strings in path
  399. dwRequired = ExpandEnvironmentStringsA(
  400. szValue,
  401. szExpanded,
  402. sizeof(szExpanded)
  403. );
  404. // load subagent library - no flags set
  405. fOk = AddSubagentByDll(szExpanded, 0);
  406. break; // bail...
  407. }
  408. // initialize buffer sizes
  409. dwNameSize = sizeof(szName);
  410. dwValueSize = sizeof(szValue);
  411. // next
  412. dwIndex++;
  413. } else if (lStatus == ERROR_NO_MORE_ITEMS) {
  414. // failure
  415. fOk = FALSE;
  416. }
  417. }
  418. // release handle
  419. RegCloseKey(hKey);
  420. }
  421. else
  422. {
  423. // the registry key for this subagent could not be located.
  424. ReportSnmpEvent(
  425. SNMP_EVENT_INVALID_EXTENSION_AGENT_KEY,
  426. 1,
  427. &pKey,
  428. lStatus);
  429. }
  430. return fOk;
  431. }
  432. ///////////////////////////////////////////////////////////////////////////////
  433. // //
  434. // Public procedures //
  435. // //
  436. ///////////////////////////////////////////////////////////////////////////////
  437. BOOL
  438. AllocSLE(
  439. PSUBAGENT_LIST_ENTRY * ppSLE,
  440. LPSTR pPathname,
  441. UCHAR uchInitFlags
  442. )
  443. /*++
  444. Routine Description:
  445. Allocates trap destination structure and initializes.
  446. Arguments:
  447. ppSLE - pointer to receive pointer to entry.
  448. pPathname - pointer to subgent's dll path.
  449. Return Values:
  450. Returns true if successful.
  451. --*/
  452. {
  453. BOOL fOk = FALSE;
  454. PSUBAGENT_LIST_ENTRY pSLE = NULL;
  455. // attempt to allocate structure
  456. pSLE = AgentMemAlloc(sizeof(SUBAGENT_LIST_ENTRY));
  457. // validate
  458. if (pSLE != NULL) {
  459. // allocate memory for trap destination string
  460. pSLE->pPathname = AgentMemAlloc(strlen(pPathname)+1);
  461. // validate
  462. if (pSLE->pPathname != NULL) {
  463. // transfer trap destination string
  464. strcpy(pSLE->pPathname, pPathname);
  465. // set the initial flags value
  466. pSLE->uchFlags = uchInitFlags;
  467. // initialize list of supported regions
  468. InitializeListHead(&pSLE->SupportedRegions);
  469. // success
  470. fOk = TRUE;
  471. }
  472. // cleanup
  473. if (!fOk) {
  474. // release
  475. FreeSLE(pSLE);
  476. // re-init
  477. pSLE = NULL;
  478. }
  479. }
  480. // transfer
  481. *ppSLE = pSLE;
  482. return fOk;
  483. }
  484. BOOL
  485. FreeSLE(
  486. PSUBAGENT_LIST_ENTRY pSLE
  487. )
  488. /*++
  489. Routine Description:
  490. Releases subagent structure.
  491. Arguments:
  492. pSLE - pointer to list entry to be freed.
  493. Return Values:
  494. Returns true if successful.
  495. --*/
  496. {
  497. BOOL fOk = TRUE;
  498. // validate pointer
  499. if (pSLE != NULL) {
  500. SNMPDBG((
  501. SNMP_LOG_VERBOSE,
  502. "SNMP: SVC: unloading %s.\n",
  503. pSLE->pPathname
  504. ));
  505. // release manager structures
  506. UnloadRegions(&pSLE->SupportedRegions);
  507. // validate subagent dll handle
  508. if (pSLE->hSubagentDll != NULL) {
  509. __try {
  510. if (pSLE->pfnSnmpExtensionClose != NULL)
  511. (*pSLE->pfnSnmpExtensionClose)();
  512. // unload subagent
  513. FreeLibrary(pSLE->hSubagentDll);
  514. } __except (EXCEPTION_EXECUTE_HANDLER) {
  515. SNMPDBG((
  516. SNMP_LOG_ERROR,
  517. "SNMP: SVC: exception 0x%08lx unloading %s.\n",
  518. GetExceptionCode(),
  519. pSLE->pPathname
  520. ));
  521. }
  522. }
  523. // release string
  524. AgentMemFree(pSLE->pPathname);
  525. // release structure
  526. AgentMemFree(pSLE);
  527. }
  528. return TRUE;
  529. }
  530. BOOL
  531. LoadSubagents(
  532. )
  533. /*++
  534. Routine Description:
  535. Constructs list of subagents.
  536. Arguments:
  537. None.
  538. Return Values:
  539. Returns true if successful.
  540. --*/
  541. {
  542. HKEY hKey;
  543. LONG lStatus;
  544. DWORD dwIndex;
  545. DWORD dwNameSize;
  546. DWORD dwValueSize;
  547. DWORD dwValueType;
  548. TCHAR szName[MAX_PATH];
  549. TCHAR szValue[MAX_PATH];
  550. LPTSTR pszKey = REG_KEY_EXTENSION_AGENTS;
  551. BOOL fOk = FALSE;
  552. SNMPDBG((
  553. SNMP_LOG_TRACE,
  554. "SNMP: SVC: loading subagents.\n"
  555. ));
  556. // open registry subkey
  557. lStatus = RegOpenKeyEx(
  558. HKEY_LOCAL_MACHINE,
  559. pszKey,
  560. 0,
  561. KEY_READ,
  562. &hKey
  563. );
  564. // validate return code
  565. if (lStatus == ERROR_SUCCESS) {
  566. // initialize
  567. dwIndex = 0;
  568. // initialize buffer sizes
  569. dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
  570. dwValueSize = sizeof(szValue); // size in number of bytes
  571. // loop until error or end of list
  572. while (lStatus == ERROR_SUCCESS) {
  573. // read next value
  574. lStatus = RegEnumValue(
  575. hKey,
  576. dwIndex,
  577. szName,
  578. &dwNameSize,
  579. NULL,
  580. &dwValueType,
  581. (LPBYTE)szValue,
  582. &dwValueSize
  583. );
  584. // validate return code
  585. if (lStatus == ERROR_SUCCESS) {
  586. // add subagent to list
  587. AddSubagentByKey(szValue);
  588. // re-initialize buffer sizes
  589. dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
  590. dwValueSize = sizeof(szValue); // size in number of bytes
  591. // next
  592. dwIndex++;
  593. } else if (lStatus == ERROR_NO_MORE_ITEMS) {
  594. // success
  595. fOk = TRUE;
  596. }
  597. }
  598. }
  599. if (!fOk) {
  600. SNMPDBG((
  601. SNMP_LOG_ERROR,
  602. "SNMP: SVC: error %d processing Subagents subkey.\n",
  603. lStatus
  604. ));
  605. // report event
  606. ReportSnmpEvent(
  607. SNMP_EVENT_INVALID_REGISTRY_KEY,
  608. 1,
  609. &pszKey,
  610. lStatus
  611. );
  612. }
  613. return fOk;
  614. }
  615. BOOL
  616. UnloadSubagents(
  617. )
  618. /*++
  619. Routine Description:
  620. Destroys list of subagents.
  621. Arguments:
  622. None.
  623. Return Values:
  624. Returns true if successful.
  625. --*/
  626. {
  627. PLIST_ENTRY pLE;
  628. PSUBAGENT_LIST_ENTRY pSLE;
  629. // process entries until list is empty
  630. while (!IsListEmpty(&g_Subagents)) {
  631. // extract next entry from head of list
  632. pLE = RemoveHeadList(&g_Subagents);
  633. // retrieve pointer to community structure
  634. pSLE = CONTAINING_RECORD(pLE, SUBAGENT_LIST_ENTRY, Link);
  635. // release
  636. FreeSLE(pSLE);
  637. }
  638. return TRUE;
  639. }