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.

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