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.

641 lines
20 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. main.c
  5. Abstract:
  6. SNMP Extension Agent for Http Service on Windows NT.
  7. Created:
  8. MuraliK 22-Feb-1995
  9. Revision History:
  10. Murali R. Krishnan (MuraliK) 16-Nov-1995 Removed undoc apis
  11. --*/
  12. /************************************************************
  13. * Include Headers
  14. ************************************************************/
  15. # include "mib.h"
  16. # include "apiutil.h"
  17. #define DEFAULT_TRACE_FLAGS (DEBUG_SNMP_RESOLVE)
  18. # include "dbgutil.h"
  19. # include "iis64.h"
  20. /************************************************************
  21. * Variable Definitions
  22. ************************************************************/
  23. //
  24. // Definition of the MIB objects
  25. //
  26. //
  27. // The InternetServer section of the OID tree is organized as follows:
  28. //
  29. // iso(1)
  30. // org(3)
  31. // dod(6)
  32. // internet(1)
  33. // private(4)
  34. // enterprises(1)
  35. // microsoft(311)
  36. // software(1)
  37. // InternetServer(7)
  38. // InetSrvCommon(1)
  39. // InetSrvStatistics(1)
  40. // FtpServer(2)
  41. // FtpStatistics(1)
  42. // HttpServer(3)
  43. // HttpStatistics(1)
  44. // GopherServer(4)
  45. // GopherStatistics(1)
  46. //
  47. static UINT sg_rguiPrefix[] = { 1, 3, 6, 1, 4, 1, 311, 1, 7, 3};
  48. static AsnObjectIdentifier sg_MibOidPrefix =
  49. OID_FROM_UINT_ARRAY( sg_rguiPrefix);
  50. # define HTTP_PREFIX_OID_LENGTH ( GET_OID_LENGTH( sg_MibOidPrefix))
  51. # define HTTP_STATISTICS_OID_SUFFIX ( 1)
  52. //
  53. // Following is the global description of all MIB Entries ( Mibe s) for
  54. // Http Service.
  55. // Definition appears as:
  56. // Mibe( MIB Entry Name, Index in MIB Block, HttpStatisticsField)
  57. //
  58. // Incidentally, MIB Entry suffix coincides with the entry name in OID Tree
  59. //
  60. // Any New MIB should be added here. and dont change use of after this defn.
  61. //
  62. # define ALL_MIB_ENTRIES() \
  63. Mibe( TotalBytesSent_HighWord, 1, TotalBytesSent.HighPart) \
  64. Mibe( TotalBytesSent_LowWord, 2, TotalBytesSent.LowPart) \
  65. Mibe( TotalBytesReceived_HighWord, 3, TotalBytesReceived.HighPart) \
  66. Mibe( TotalBytesReceived_LowWord, 4, TotalBytesReceived.LowPart) \
  67. Mibe( TotalFilesSent, 5, TotalFilesSent) \
  68. Mibe( TotalFilesReceived, 6, TotalFilesReceived) \
  69. Mibe( CurrentAnonymousUsers, 7, CurrentAnonymousUsers) \
  70. Mibe( CurrentNonAnonymousUsers, 8, CurrentNonAnonymousUsers) \
  71. Mibe( TotalAnonymousUsers, 9, TotalAnonymousUsers) \
  72. Mibe( TotalNonAnonymousUsers, 10, TotalNonAnonymousUsers) \
  73. Mibe( MaxAnonymousUsers, 11, MaxAnonymousUsers) \
  74. Mibe( MaxNonAnonymousUsers, 12, MaxNonAnonymousUsers) \
  75. Mibe( CurrentConnections, 13, CurrentConnections) \
  76. Mibe( MaxConnections, 14, MaxConnections) \
  77. Mibe( ConnectionAttempts, 15, ConnectionAttempts) \
  78. Mibe( LogonAttempts, 16, LogonAttempts) \
  79. Mibe( TotalOptions, 17, TotalOptions) \
  80. Mibe( TotalGets, 18, TotalGets) \
  81. Mibe( TotalPosts, 19, TotalPosts) \
  82. Mibe( TotalHeads, 20, TotalHeads) \
  83. Mibe( TotalPuts , 21, TotalPuts) \
  84. Mibe( TotalDeletes , 22, TotalDeletes) \
  85. Mibe( TotalTraces , 23, TotalTraces) \
  86. Mibe( TotalMove, 24, TotalMove) \
  87. Mibe( TotalCopy, 25, TotalCopy) \
  88. Mibe( TotalMkcol, 26, TotalMkcol) \
  89. Mibe( TotalPropfind, 27, TotalPropfind) \
  90. Mibe( TotalProppatch, 28, TotalProppatch) \
  91. Mibe( TotalSearch, 29, TotalSearch) \
  92. Mibe( TotalLock, 30, TotalLock) \
  93. Mibe( TotalUnlock, 31, TotalUnlock) \
  94. Mibe( TotalOthers, 32, TotalOthers) \
  95. Mibe( CurrentCGIRequests, 33, CurrentCGIRequests) \
  96. Mibe( CurrentBGIRequests, 34, CurrentBGIRequests) \
  97. Mibe( TotalCGIRequests, 35, TotalCGIRequests) \
  98. Mibe( TotalBGIRequests, 36, TotalBGIRequests) \
  99. Mibe( MaxCGIRequests, 37, MaxCGIRequests) \
  100. Mibe( MaxBGIRequests, 38, MaxBGIRequests) \
  101. Mibe( CurrentBlockedRequests, 39, CurrentBlockedRequests) \
  102. Mibe( TotalBlockedRequests, 40, TotalBlockedRequests) \
  103. Mibe( TotalAllowedRequests, 41, TotalAllowedRequests) \
  104. Mibe( TotalRejectedRequests, 42, TotalRejectedRequests) \
  105. Mibe( TotalNotFoundErrors, 43, TotalNotFoundErrors) \
  106. Mibe( TotalLockedErrors, 44, TotalLockedErrors) \
  107. Mibe( MeasuredBandwidth, 45, MeasuredBw) \
  108. Mibe( CurrentCalAuth, 46, CurrentCalAuth) \
  109. Mibe( MaxCalAuth, 47, MaxCalAuth) \
  110. Mibe( TotalFailedCalAuth, 48, TotalFailedCalAuth) \
  111. Mibe( CurrentCalSsl, 49, CurrentCalSsl) \
  112. Mibe( MaxCalSsl, 50, MaxCalSsl) \
  113. Mibe( TotalFailedCalSsl, 51, TotalFailedCalSsl)
  114. //
  115. // Individual OID Definitions.
  116. // All Leaf variables should have a zero appended to their OID to indicate
  117. // that it is the only instance of this variable and that it exists.
  118. // Declare just the id's starting from next to the prefix given above.
  119. //
  120. //
  121. // Few Convenience Macros for MIB entries addition.
  122. //
  123. # define MIB_VAR_NAME( NameSuffix) MIB_ ## NameSuffix
  124. # define DEFINE_MIBOID( NameSuffix, uiArray) \
  125. UINT MIB_VAR_NAME( NameSuffix)[] = uiArray
  126. # define DEFINE_MIBOID_LEAF( NameSuffix, NodeNumber) \
  127. UINT MIB_VAR_NAME( NameSuffix)[] = \
  128. { HTTP_STATISTICS_OID_SUFFIX, ( NodeNumber), 0 }
  129. //
  130. // Define all the OIDs. First define the higher level node and then leaves.
  131. //
  132. DEFINE_MIBOID( Statistics, { HTTP_STATISTICS_OID_SUFFIX} );
  133. //
  134. // Define the Leaf OIDs.
  135. //
  136. # define Mibe( NameSuffix, Index, FieldName) \
  137. DEFINE_MIBOID_LEAF( NameSuffix, Index);
  138. //
  139. // Expand the macro ALL_MIB_ENTRIES to obtain definitions of MIB Leafs.
  140. //
  141. ALL_MIB_ENTRIES()
  142. # undef Mibe
  143. //
  144. // MIB Variable definition
  145. //
  146. //
  147. // Define Mibe() to be for variable definitions of counters.
  148. // Note that the comma is appearing before a new counter name. It is used
  149. // for structure initialization.
  150. //
  151. # define OFFSET_IN_HTTP_STATISTICS( Field) \
  152. FIELD_OFFSET( W3_STATISTICS_1, Field)
  153. # define Mibe( NameSuffix, Index, Field) \
  154. , MIB_COUNTER( OID_FROM_UINT_ARRAY( MIB_VAR_NAME( NameSuffix)), \
  155. OFFSET_IN_HTTP_STATISTICS(Field), \
  156. MibStatisticsWorker)
  157. static MIB_ENTRY sg_rgHttpMib[] = {
  158. //
  159. // Statistics
  160. //
  161. MIB_ENTRY_HEADER( OID_FROM_UINT_ARRAY( MIB_VAR_NAME( Statistics)))
  162. ALL_MIB_ENTRIES()
  163. };
  164. # undef Mibe
  165. static MIB_ENTRIES sg_HttpMibs =
  166. {
  167. &sg_MibOidPrefix,
  168. ( sizeof( sg_rgHttpMib) / sizeof( MIB_ENTRY)),
  169. sg_rgHttpMib
  170. };
  171. DECLARE_DEBUG_PRINTS_OBJECT();
  172. #ifndef _NO_TRACING_
  173. #include <initguid.h>
  174. DEFINE_GUID(IisW3MibGuid,
  175. 0x784d891C, 0xaa8c, 0x11d2, 0x92, 0x5e, 0x00, 0xc0, 0x4f, 0x72, 0xd9, 0x0e);
  176. #else
  177. DECLARE_DEBUG_VARIABLE();
  178. #endif
  179. /************************************************************
  180. * Functions
  181. ************************************************************/
  182. BOOL WINAPI
  183. DllLibMain(
  184. IN HINSTANCE hinstDll,
  185. IN DWORD fdwReason,
  186. IN LPVOID lpvContext OPTIONAL)
  187. /*++
  188. Routine Description:
  189. This function DllLibMain() is the main initialization function for
  190. Http MIB DLL. It initialises local variables and prepares the
  191. interface for the process to use SNMP Extension Agents for HTTP service.
  192. Messages Actions
  193. ProcessAttach Initializes winsock and data structures.
  194. It fails if winsock has not already been started.
  195. ProcessDetach Cleans up local data structures and disconnects from
  196. winsock.
  197. Arguments:
  198. hinstDll Instance Handle of the DLL
  199. fdwReason Reason why NT called this DLL
  200. lpvReserved Reserved parameter for future use.
  201. Return Value:
  202. Returns TRUE is successful; otherwise FALSE is returned.
  203. --*/
  204. {
  205. BOOL fReturn = TRUE;
  206. switch (fdwReason ) {
  207. case DLL_PROCESS_ATTACH: {
  208. //
  209. // Initialize various modules
  210. //
  211. break;
  212. } /* case DLL_PROCESS_ATTACH */
  213. case DLL_PROCESS_DETACH: {
  214. //
  215. // Only cleanup when we are called because of a FreeLibrary().
  216. // i.e., when lpvContext == NULL
  217. // If we are called because of a process termination, dont free anything
  218. // the system will free resources and memory for us.
  219. //
  220. if ( lpvContext == NULL) {
  221. //
  222. // Code to be executed on successful termination
  223. //
  224. DELETE_DEBUG_PRINT_OBJECT();
  225. }
  226. break;
  227. } /* case DLL_PROCESS_DETACH */
  228. default:
  229. break;
  230. } /* switch */
  231. return ( fReturn);
  232. } /* DllLibMain() */
  233. /************************************************************
  234. * Entry Points of SNMP Extension DLL For Http Service
  235. ************************************************************/
  236. //
  237. // Extension Agent DLLs need access to elapsed time agent has been active.
  238. // This is implemented by initializing the Extension Agent with a time zero
  239. // reference, and allowing the agent to compute elapsed time by subtracting
  240. // the time zero reference from the current system time. This example
  241. // Extension Agent implements this reference with dwTimeZero.
  242. //
  243. DWORD dwTimeZero = 0;
  244. BOOL
  245. SnmpExtensionInit(
  246. IN DWORD dwTimeZeroReference,
  247. OUT HANDLE * phPollForTrapEvent,
  248. OUT AsnObjectIdentifier * pAsnOidSupportedView
  249. )
  250. /*++
  251. Description:
  252. The Extension Agent DLLs provide this entry point SnmpExtensionInit()
  253. to co-ordinate the initializations of the extension agent and the
  254. extendible agent.
  255. The Extendible agent provides extension agent with a time zero reference.
  256. The Extension Agent provides Extendible agent with an Event Handle
  257. for communicating occurences of traps.
  258. The Extension Agent also provides Extendible agent with an ObjectId
  259. representing the root of the MIB structure
  260. that it (extension) supports.
  261. Arguments:
  262. dwTimeZeroReference DWORD containing the Time Zero Reference for sync.
  263. phPollForTrapEvent pointer to handle which on successful return
  264. may contain an event handle to be polled for
  265. traps.
  266. pAsnOidSupportedView pointer to ASN ( Abstract Syntax Notation OID)
  267. that contains the oid representing root of the
  268. MIB structure.
  269. Returns:
  270. TRUE on success and FALSE if there is any failure.
  271. --*/
  272. {
  273. #ifndef _NO_TRACING_
  274. CREATE_DEBUG_PRINT_OBJECT( "httpmib", IisW3MibGuid);
  275. #else
  276. CREATE_DEBUG_PRINT_OBJECT( "httpmib");
  277. SET_DEBUG_FLAGS( DEBUG_SNMP_RESOLVE); // enable flags if needed.
  278. #endif
  279. IF_DEBUG( SNMP_INIT) {
  280. DBGPRINTF( ( DBG_CONTEXT,
  281. "Entering SnmpExtensionInit( %u, %08x, %08x)\n",
  282. dwTimeZeroReference,
  283. phPollForTrapEvent,
  284. pAsnOidSupportedView));
  285. }
  286. //
  287. // Record the time reference provided by the Extendible Agent.
  288. //
  289. dwTimeZero = dwTimeZeroReference;
  290. //
  291. // Indicate the MIB view supported by this Extension Agent, an object
  292. // identifier representing the sub root of the MIB that is supported.
  293. //
  294. *pAsnOidSupportedView = sg_MibOidPrefix; // NOTE! structure copy
  295. //
  296. // Though the following is a handle, dont use INVALID_HANDLE_VALUE ( -1)
  297. // because that constant is only for few people ( Win32). But all through
  298. // NT invalid handle value is NULL ( 0).
  299. //
  300. *phPollForTrapEvent = NULL;
  301. //
  302. // Indicate that Extension Agent initialization was sucessfull.
  303. //
  304. return ( TRUE);
  305. } // SnmpExtensionInit()
  306. BOOL
  307. SnmpExtensionTrap(
  308. OUT AsnObjectIdentifier * pAsnOidEnterprise,
  309. OUT AsnInteger * pAsniGenericTrap,
  310. OUT AsnInteger * pAsniSpecificTrap,
  311. OUT AsnTimeticks * pAsnTimeStamp,
  312. OUT RFC1157VarBindList * pRfcVariableBindings
  313. )
  314. /*++
  315. Description:
  316. This function is used to communicate traps to the Extendible Agent.
  317. The Extendible Agent will invoke this entry point when the trap event
  318. ( supplied at the initialization time) is asserted, which indicates
  319. that zero or more traps had occured.
  320. The Extendible agent will repeatedly query this function till this
  321. function returns FALSE.
  322. Arguments:
  323. pAsnOidEnterprise pointer to ASN OID for Enterprise, indicating
  324. original enterprise generating trap.
  325. pAsniGenericTrap pointer to ASN Integer which on return will
  326. contain the indication of the generic trap.
  327. pAsniSpecificTrap pointer to ASN Integer which on return will
  328. contain the specific trap generated.
  329. pAsnTimeStamp pointer to ASN containing the received Time-Stamp.
  330. pRfcVariableBindings pointer to RFC 1157 compliant variable bindings.
  331. Returns:
  332. TRUE if success and there are more traps to be queried.
  333. FALSE if all traps are answered and work done.
  334. --*/
  335. {
  336. IF_DEBUG( SNMP_TRAP) {
  337. DBGPRINTF( ( DBG_CONTEXT,
  338. " Entering SnmpExtensionTrap( pOidE=%08x, pGenTrap=%08x,"
  339. " pSpecificTrap = %08x, pTimeStamp=%08x, pVars=%08x)\n",
  340. pAsnOidEnterprise,
  341. pAsniGenericTrap,
  342. pAsniSpecificTrap,
  343. pAsnTimeStamp,
  344. pRfcVariableBindings));
  345. }
  346. //
  347. // We don't support traps (yet).
  348. //
  349. return ( FALSE);
  350. } // SnmpExtensionTrap()
  351. BOOL
  352. SnmpExtensionQuery(
  353. IN BYTE bRequestType,
  354. IN OUT RFC1157VarBindList * pRfcVariableBindings,
  355. OUT AsnInteger * pAsniErrorStatus,
  356. OUT AsnInteger * pAsniErrorIndex
  357. )
  358. /*++
  359. Description:
  360. This function is called by Extendible Agent to resolve the SNMP requests
  361. for queries on MIB Variables in the Extension Agent's supported MIB view.
  362. ( which was supplied at initialization time).
  363. The Request Type is GET, GETNEXT, and SET.
  364. Arguments:
  365. bRequestType byte containing the type of request.
  366. It can be one of
  367. ASN_RFC1157_GETREQUEST
  368. ASN_RFC1157_GETNEXTREQUEST
  369. ASN_RFC1157_SETREQUEST
  370. pRfcVariableBindings
  371. pointer to RFC 1157 compliant variable bindings.
  372. pAsniErrorStatus
  373. pointer to ASN Integer for Error Status
  374. pAsniErrorIndex
  375. pointer to ASN INteger giving the index for error.
  376. Returns:
  377. TRUE on success and FALSE on failure.
  378. --*/
  379. {
  380. W3_STATISTICS_1 HttpStatistics;
  381. LPW3_STATISTICS_1 pHttpStatistics = NULL;
  382. NET_API_STATUS Status;
  383. IF_DEBUG( SNMP_QUERY) {
  384. DBGPRINTF( ( DBG_CONTEXT,
  385. " Entering SnmpExtensionQuery( Req=0x%x, pVars=%08x,"
  386. " pAsniError=%08x, pAsniIndex=%08x).\n",
  387. bRequestType, pRfcVariableBindings,
  388. pAsniErrorStatus, pAsniErrorIndex));
  389. }
  390. //
  391. // Try to query the statistics now so we'll have a consitent
  392. // view across all variable bindings.
  393. //
  394. Status = W3QueryStatistics2(
  395. NULL, // pszServer
  396. 0,
  397. INET_INSTANCE_GLOBAL,
  398. 0,
  399. (LPBYTE *) &pHttpStatistics );
  400. //
  401. // Status Errors not checked for here!
  402. // Reason:
  403. // If the verb is GET_NEXT beyond the block we support,
  404. // then there is no need to worry about the error at all.
  405. // If the verb is GET within the block, it will get NULL value
  406. // ( due the memset() done above).
  407. //
  408. try
  409. {
  410. //
  411. // Iterate through the variable bindings list to resolve individual
  412. // variable bindings.
  413. //
  414. RFC1157VarBind * pVarBinding;
  415. for( pVarBinding = pRfcVariableBindings->list;
  416. pVarBinding < ( pRfcVariableBindings->list +
  417. pRfcVariableBindings->len);
  418. pVarBinding++ ) {
  419. *pAsniErrorStatus = ResolveVarBinding( pVarBinding,
  420. bRequestType,
  421. pHttpStatistics,
  422. &sg_HttpMibs);
  423. //
  424. // Test and handle case where Get Next past end of MIB view
  425. // supported by this Extension Agent occurs. Special
  426. // processing is required to communicate this situation to
  427. // the Extendible Agent so it can take appropriate action,
  428. // possibly querying other Extension Agents.
  429. //
  430. if(( *pAsniErrorStatus == SNMP_ERRORSTATUS_NOSUCHNAME ) &&
  431. ( bRequestType == MIB_GETNEXT ) ) {
  432. IF_DEBUG( SNMP_QUERY) {
  433. DBGPRINTF( ( DBG_CONTEXT,
  434. "At the End of Mib View for this Agent."
  435. "Incrementing the variable to next block.\n"));
  436. }
  437. *pAsniErrorStatus = SNMP_ERRORSTATUS_NOERROR;
  438. //
  439. // Modify variable binding of such variables so the OID
  440. // points just outside the MIB view supported by this
  441. // Extension Agent. The Extendible Agent tests for this,
  442. // and takes appropriate action.
  443. //
  444. SNMP_oidfree( &pVarBinding->name );
  445. SNMP_oidcpy( &pVarBinding->name, &sg_MibOidPrefix);
  446. pVarBinding->name.ids[ HTTP_PREFIX_OID_LENGTH - 1]++;
  447. }
  448. //
  449. // If an error was indicated, communicate error status and error
  450. // index to the Extendible Agent. The Extendible Agent will
  451. // ensure that the origional variable bindings are returned in
  452. // the response packet.
  453. *pAsniErrorIndex =
  454. (( *pAsniErrorStatus != SNMP_ERRORSTATUS_NOERROR ) ?
  455. (( DIFF(pVarBinding - pRfcVariableBindings->list)) + 1) : 0);
  456. } // for
  457. } // try
  458. except( EXCEPTION_EXECUTE_HANDLER ) {
  459. //
  460. // For now do nothing.
  461. //
  462. IF_DEBUG( SNMP_QUERY) {
  463. DBGPRINTF( ( DBG_CONTEXT,
  464. "Exception occured while resolving "
  465. " SnmpExtensionQuery()"));
  466. }
  467. }
  468. if ( pHttpStatistics )
  469. {
  470. MIDL_user_free( pHttpStatistics );
  471. }
  472. IF_DEBUG( SNMP_QUERY) {
  473. DBGPRINTF( ( DBG_CONTEXT,
  474. "Returning from GophMib::Query() with "
  475. " Error Status = %u. Error Index = %u.\n",
  476. *pAsniErrorStatus,
  477. *pAsniErrorIndex));
  478. }
  479. return ( SNMPAPI_NOERROR);
  480. } // SnmpExtensionQuery()