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.

621 lines
15 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. mib.c
  5. Abstract:
  6. SNMP Extension Agent for Windows NT.
  7. Created:
  8. 18-Feb-1995
  9. Revision History:
  10. --*/
  11. #include "mib.h"
  12. //
  13. // Private constants & macros.
  14. //
  15. //
  16. // This macro creates a MIB_ENTRY for a MIB group header.
  17. //
  18. #define MIB_ENTRY_HEADER(oid) \
  19. { \
  20. { OID_SIZEOF(oid), (oid) }, \
  21. -1, \
  22. MIB_NOACCESS, \
  23. NULL, \
  24. ASN_RFC1155_OPAQUE, \
  25. }
  26. //
  27. // This macro creates a generic MIB_ENTRY for a MIB variable.
  28. //
  29. #define MIB_ENTRY_ITEM(oid,field,type) \
  30. { \
  31. { OID_SIZEOF(oid), (oid) }, \
  32. FIELD_OFFSET(FTP_STATISTICS_0,field), \
  33. MIB_ACCESS_READ, \
  34. MIB_Stat, \
  35. (type), \
  36. }
  37. //
  38. // These macros create COUNTER and INTEGER type MIB_ENTRYs.
  39. //
  40. #define MIB_COUNTER(oid,field) \
  41. MIB_ENTRY_ITEM(oid, field, ASN_RFC1155_COUNTER)
  42. #define MIB_INTEGER(oid,field) \
  43. MIB_ENTRY_ITEM(oid, field, ASN_INTEGER)
  44. //
  45. // Private types.
  46. //
  47. typedef UINT (*LPMIBFUNC)( UINT Action,
  48. struct _MIB_ENTRY * MibPtr,
  49. RFC1157VarBind * VarBind,
  50. LPVOID Statistics
  51. );
  52. typedef struct _MIB_ENTRY
  53. {
  54. //
  55. // The OID for this MIB variable.
  56. //
  57. AsnObjectIdentifier Oid;
  58. //
  59. // The offset within the statistics structure for this
  60. // variable.
  61. //
  62. LONG FieldOffset;
  63. //
  64. // Access type (read, write, read-write, none).
  65. //
  66. UINT Access;
  67. //
  68. // Pointer to a function that manages this variable.
  69. //
  70. LPMIBFUNC MibFunc;
  71. //
  72. // Type (integer, counter, gauge, etc.)
  73. //
  74. BYTE Type;
  75. } MIB_ENTRY;
  76. //
  77. // Private globals.
  78. //
  79. //
  80. // The InternetServer section of the OID tree is organized as follows:
  81. //
  82. // iso(1)
  83. // org(3)
  84. // dod(6)
  85. // internet(1)
  86. // private(4)
  87. // enterprises(1)
  88. // microsoft(311)
  89. // software(1)
  90. // InternetServer(7)
  91. // InetSrvCommon(1)
  92. // InetSrvStatistics(1)
  93. // FtpServer(2)
  94. // FtpStatistics(1)
  95. // W3Server(3)
  96. // W3Statistics(1)
  97. // GopherServer(4)
  98. // GopherStatistics(1)
  99. //
  100. UINT OID_Prefix[] = { 1, 3, 6, 1, 4, 1, 311, 1, 7, 2 };
  101. AsnObjectIdentifier MIB_OidPrefix = { OID_SIZEOF(OID_Prefix), OID_Prefix };
  102. //
  103. // OID definitions.
  104. //
  105. // All leaf variables have a zero appended to their OID to indicate
  106. // that it is the only instance of this variable and that it exists.
  107. //
  108. UINT MIB_Statistics[] = { 1 };
  109. UINT MIB_TotalBytesSent_HighWord[] = { 1, 1, 0 };
  110. UINT MIB_TotalBytesSent_LowWord[] = { 1, 2, 0 };
  111. UINT MIB_TotalBytesReceived_HighWord[] = { 1, 3, 0 };
  112. UINT MIB_TotalBytesReceived_LowWord[] = { 1, 4, 0 };
  113. UINT MIB_TotalFilesSent[] = { 1, 5, 0 };
  114. UINT MIB_TotalFilesReceived[] = { 1, 6, 0 };
  115. UINT MIB_CurrentAnonymousUsers[] = { 1, 7, 0 };
  116. UINT MIB_CurrentNonAnonymousUsers[] = { 1, 8, 0 };
  117. UINT MIB_TotalAnonymousUsers[] = { 1, 9, 0 };
  118. UINT MIB_TotalNonAnonymousUsers[] = { 1, 10, 0 };
  119. UINT MIB_MaxAnonymousUsers[] = { 1, 11, 0 };
  120. UINT MIB_MaxNonAnonymousUsers[] = { 1, 12, 0 };
  121. UINT MIB_CurrentConnections[] = { 1, 13, 0 };
  122. UINT MIB_MaxConnections[] = { 1, 14, 0 };
  123. UINT MIB_ConnectionAttempts[] = { 1, 15, 0 };
  124. UINT MIB_LogonAttempts[] = { 1, 16, 0 };
  125. //
  126. // Private prototypes.
  127. //
  128. UINT
  129. MIB_leaf_func(
  130. UINT Action,
  131. MIB_ENTRY * MibPtr,
  132. RFC1157VarBind * VarBind,
  133. LPVOID Statistics
  134. );
  135. UINT
  136. MIB_Stat(
  137. UINT Action,
  138. MIB_ENTRY * MibPtr,
  139. RFC1157VarBind * VarBind,
  140. LPVOID Statistics
  141. );
  142. UINT
  143. GetNextVar(
  144. RFC1157VarBind * VarBind,
  145. MIB_ENTRY * MibPtr,
  146. LPVOID Statistics
  147. );
  148. //
  149. // MIB definiton
  150. //
  151. MIB_ENTRY Mib[] =
  152. {
  153. //
  154. // Statistics.
  155. //
  156. MIB_ENTRY_HEADER( MIB_Statistics ),
  157. MIB_COUNTER( MIB_TotalBytesSent_HighWord, TotalBytesSent.HighPart ),
  158. MIB_COUNTER( MIB_TotalBytesSent_LowWord, TotalBytesSent.LowPart ),
  159. MIB_COUNTER( MIB_TotalBytesReceived_HighWord, TotalBytesReceived.HighPart ),
  160. MIB_COUNTER( MIB_TotalBytesReceived_LowWord, TotalBytesReceived.LowPart ),
  161. MIB_COUNTER( MIB_TotalFilesSent, TotalFilesSent ),
  162. MIB_COUNTER( MIB_TotalFilesReceived, TotalFilesReceived ),
  163. MIB_INTEGER( MIB_CurrentAnonymousUsers, CurrentAnonymousUsers ),
  164. MIB_INTEGER( MIB_CurrentNonAnonymousUsers, CurrentNonAnonymousUsers ),
  165. MIB_COUNTER( MIB_TotalAnonymousUsers, TotalAnonymousUsers ),
  166. MIB_COUNTER( MIB_TotalNonAnonymousUsers, TotalNonAnonymousUsers ),
  167. MIB_COUNTER( MIB_MaxAnonymousUsers, MaxAnonymousUsers ),
  168. MIB_COUNTER( MIB_MaxNonAnonymousUsers, MaxNonAnonymousUsers ),
  169. MIB_INTEGER( MIB_CurrentConnections, CurrentConnections ),
  170. MIB_COUNTER( MIB_MaxConnections, MaxConnections ),
  171. MIB_COUNTER( MIB_ConnectionAttempts, ConnectionAttempts ),
  172. MIB_COUNTER( MIB_LogonAttempts, LogonAttempts )
  173. };
  174. #define NUM_MIB_ENTRIES ( sizeof(Mib) / sizeof(MIB_ENTRY) )
  175. //
  176. // Public functions.
  177. //
  178. UINT
  179. ResolveVarBind(
  180. RFC1157VarBind * VarBind,
  181. UINT PduAction,
  182. LPVOID Statistics
  183. )
  184. //
  185. // ResolveVarBind
  186. // Resolves a single variable binding. Modifies the variable on a GET
  187. // or a GET-NEXT.
  188. //
  189. // Notes:
  190. //
  191. // Return Codes:
  192. // Standard PDU error codes.
  193. //
  194. // Error Codes:
  195. // None.
  196. //
  197. {
  198. MIB_ENTRY *MibPtr;
  199. AsnObjectIdentifier TempOid;
  200. int CompResult;
  201. UINT i;
  202. UINT nResult;
  203. DWORD TableIndex;
  204. BOOL fTableMatch = FALSE;
  205. //
  206. // Search for a varbind name in the MIB.
  207. //
  208. MibPtr = NULL;
  209. for( i = 0 ; i < NUM_MIB_ENTRIES ; i++ )
  210. {
  211. //
  212. // Create a fully qualified OID for the current item in the MIB.
  213. //
  214. SNMP_oidcpy( &TempOid, &MIB_OidPrefix );
  215. SNMP_oidappend( &TempOid, &Mib[i].Oid );
  216. //
  217. // See if the given OID is in the MIB.
  218. //
  219. CompResult = SNMP_oidcmp( &VarBind->name, &TempOid );
  220. SNMP_oidfree( &TempOid );
  221. //
  222. // If result is negative, only valid operation is GET-NEXT.
  223. //
  224. if( CompResult < 0 )
  225. {
  226. //
  227. // This could be the OID of a leaf (without a trailing 0) or
  228. // it could be an invalid OID (between two valid OIDs).
  229. //
  230. if( PduAction == MIB_GETNEXT )
  231. {
  232. MibPtr = &Mib[i];
  233. SNMP_oidfree( &VarBind->name );
  234. SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
  235. SNMP_oidappend( &VarBind->name, &MibPtr->Oid );
  236. if( ( MibPtr->Type != ASN_RFC1155_OPAQUE ) &&
  237. ( MibPtr->Type != ASN_SEQUENCE ) )
  238. {
  239. PduAction = MIB_GET;
  240. }
  241. }
  242. else
  243. {
  244. nResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  245. goto Exit;
  246. }
  247. break;
  248. }
  249. else
  250. if( CompResult == 0 )
  251. {
  252. //
  253. // Found one!
  254. //
  255. MibPtr = &Mib[i];
  256. break;
  257. }
  258. }
  259. if( i < NUM_MIB_ENTRIES )
  260. {
  261. //
  262. // The associated function pointer will be NULL only if the
  263. // match was with a group OID.
  264. //
  265. if( MibPtr->MibFunc == NULL )
  266. {
  267. if( PduAction == MIB_GETNEXT )
  268. {
  269. nResult = GetNextVar( VarBind, MibPtr, Statistics );
  270. }
  271. else
  272. {
  273. nResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  274. }
  275. goto Exit;
  276. }
  277. }
  278. else
  279. {
  280. nResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  281. goto Exit;
  282. }
  283. //
  284. // Call the associated function to process the request.
  285. //
  286. nResult = (MibPtr->MibFunc)( PduAction, MibPtr, VarBind, Statistics );
  287. Exit:
  288. return nResult;
  289. } // ResolveVarBind
  290. //
  291. // Private functions.
  292. //
  293. //
  294. // MIB_leaf_func
  295. // Performs generic actions on LEAF variables in the MIB.
  296. //
  297. // Notes:
  298. //
  299. // Return Codes:
  300. // Standard PDU error codes.
  301. //
  302. // Error Codes:
  303. // None.
  304. //
  305. UINT
  306. MIB_leaf_func(
  307. UINT Action,
  308. MIB_ENTRY * MibPtr,
  309. RFC1157VarBind * VarBind,
  310. LPVOID Statistics
  311. )
  312. {
  313. UINT Result;
  314. DWORD Value;
  315. switch( Action )
  316. {
  317. case MIB_GETNEXT :
  318. //
  319. // Determine if we're at the end of our MIB.
  320. //
  321. if( ( MibPtr - Mib ) >= NUM_MIB_ENTRIES )
  322. {
  323. Result = SNMP_ERRORSTATUS_NOSUCHNAME;
  324. goto Exit;
  325. }
  326. Result = GetNextVar( VarBind, MibPtr, Statistics );
  327. if (Result != SNMP_ERRORSTATUS_NOERROR)
  328. {
  329. goto Exit;
  330. }
  331. break;
  332. case MIB_GETFIRST :
  333. case MIB_GET :
  334. //
  335. // Make sure that this variable's ACCESS is GET'able.
  336. //
  337. if( ( MibPtr->Access != MIB_ACCESS_READ ) &&
  338. ( MibPtr->Access != MIB_ACCESS_READWRITE ) )
  339. {
  340. Result = SNMP_ERRORSTATUS_NOSUCHNAME;
  341. goto Exit;
  342. }
  343. //
  344. // Setup varbind's return value.
  345. //
  346. VarBind->value.asnType = MibPtr->Type;
  347. Value = *(LPDWORD)( (LPBYTE)Statistics + MibPtr->FieldOffset );
  348. switch( VarBind->value.asnType )
  349. {
  350. case ASN_RFC1155_COUNTER:
  351. VarBind->value.asnValue.number = (AsnCounter)Value;
  352. break;
  353. case ASN_RFC1155_GAUGE:
  354. case ASN_INTEGER:
  355. VarBind->value.asnValue.number = (AsnInteger)Value;
  356. break;
  357. case ASN_RFC1155_IPADDRESS:
  358. case ASN_OCTETSTRING:
  359. //
  360. // Not supported for this MIB (yet).
  361. //
  362. Result = SNMP_ERRORSTATUS_GENERR;
  363. goto Exit;
  364. default:
  365. Result = SNMP_ERRORSTATUS_GENERR;
  366. goto Exit;
  367. }
  368. break;
  369. case MIB_SET:
  370. //
  371. // We don't support settable variables (yet).
  372. //
  373. Result = SNMP_ERRORSTATUS_NOSUCHNAME;
  374. goto Exit;
  375. default:
  376. Result = SNMP_ERRORSTATUS_GENERR;
  377. goto Exit;
  378. }
  379. Result = SNMP_ERRORSTATUS_NOERROR;
  380. Exit:
  381. return Result;
  382. } // MIB_leaf_func
  383. //
  384. // MIB_Stat
  385. // Performs specific actions on the different MIB variable.
  386. //
  387. // Notes:
  388. //
  389. // Return Codes:
  390. // Standard PDU error codes.
  391. //
  392. // Error Codes:
  393. // None.
  394. //
  395. UINT
  396. MIB_Stat(
  397. UINT Action,
  398. MIB_ENTRY * MibPtr,
  399. RFC1157VarBind * VarBind,
  400. LPVOID Statistics
  401. )
  402. {
  403. UINT Result;
  404. switch( Action )
  405. {
  406. case MIB_SET :
  407. case MIB_GETNEXT :
  408. Result = MIB_leaf_func( Action, MibPtr, VarBind, Statistics );
  409. break;
  410. case MIB_GETFIRST :
  411. case MIB_GET :
  412. //
  413. // If we have no statistics structure, bail.
  414. //
  415. if( Statistics == NULL )
  416. {
  417. Result = SNMP_ERRORSTATUS_GENERR;
  418. break;
  419. }
  420. //
  421. // If there's no field offset associated with the current
  422. // entry, also bail.
  423. //
  424. if( MibPtr->FieldOffset == -1 )
  425. {
  426. Result = SNMP_ERRORSTATUS_GENERR;
  427. break;
  428. }
  429. //
  430. // Call the generic leaf function to perform the action.
  431. //
  432. Result = MIB_leaf_func( Action, MibPtr, VarBind, Statistics );
  433. break;
  434. default :
  435. Result = SNMP_ERRORSTATUS_GENERR;
  436. break;
  437. }
  438. return Result;
  439. } // MIB_Stat
  440. UINT
  441. GetNextVar(
  442. RFC1157VarBind * VarBind,
  443. MIB_ENTRY * MibPtr,
  444. LPVOID Statistics
  445. )
  446. {
  447. UINT Result;
  448. INT i;
  449. //
  450. // Calculate the current index within the MIB array.
  451. //
  452. i = DIFF( MibPtr - Mib );
  453. //
  454. // Validate we have a reasonable value.
  455. //
  456. if( ( i < 0 ) || ( i >= NUM_MIB_ENTRIES ) )
  457. {
  458. return SNMP_ERRORSTATUS_NOSUCHNAME;
  459. }
  460. //
  461. // Scan through the remaining MIB entries.
  462. //
  463. for( i++ ; i < NUM_MIB_ENTRIES ; i++ )
  464. {
  465. MIB_ENTRY * NextMib;
  466. NextMib = &Mib[i];
  467. //
  468. // Setup varbind name of next MIB variable.
  469. //
  470. SNMP_oidfree( &VarBind->name );
  471. SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
  472. SNMP_oidappend( &VarBind->name, &NextMib->Oid );
  473. //
  474. // If the function pointer is not NULL and the type of the MIB
  475. // variable is anything but OPAQUE, then call the function to
  476. // process the MIB variable.
  477. //
  478. if( ( NextMib->MibFunc != NULL ) &&
  479. ( NextMib->Type != ASN_RFC1155_OPAQUE ) )
  480. {
  481. Result = (NextMib->MibFunc)( MIB_GETFIRST,
  482. NextMib,
  483. VarBind,
  484. Statistics );
  485. break;
  486. }
  487. }
  488. if( i >= NUM_MIB_ENTRIES )
  489. {
  490. Result = SNMP_ERRORSTATUS_NOSUCHNAME;
  491. }
  492. return Result;
  493. } // GetNextVar