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.

557 lines
15 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects.
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. mib.c
  5. Abstract:
  6. This defines Auxiliary functions for defining an SNMP Extension Agent
  7. for collecting and querying Statistical information.
  8. Author:
  9. Murali R. Krishnan ( MuraliK ) 23-Feb-1995
  10. Environment:
  11. User Mode -- Win32
  12. Project:
  13. SNMP Extension DLL for Gopher Service DLL
  14. Functions Exported:
  15. UINT ResolveVarBinding();
  16. UINT MibStatisticsWorker();
  17. Revision History:
  18. --*/
  19. /************************************************************
  20. * Include Headers
  21. ************************************************************/
  22. # include "mib.h"
  23. # include "dbgutil.h"
  24. static UINT
  25. MibLeafFunction(
  26. IN OUT RFC1157VarBind * pRfcVarBinding,
  27. IN UINT pduAction,
  28. IN struct _MIB_ENTRY * pMibeCurrent,
  29. IN struct _MIB_ENTRIES * pMibEntries,
  30. IN LPVOID pStatistics
  31. );
  32. static UINT
  33. MibGetNextVar(
  34. IN OUT RFC1157VarBind * pRfcVarBinding,
  35. IN MIB_ENTRY * pMibeCurrent,
  36. IN MIB_ENTRIES * pMibEntries,
  37. IN LPVOID pStatistics
  38. );
  39. static VOID
  40. PrintAsnObjectIdentifier( IN char * pszOidDescription,
  41. IN AsnObjectIdentifier * pAsno)
  42. {
  43. # if DBG
  44. UINT len = pAsno->idLength;
  45. UINT i;
  46. DBG_ASSERT( pAsno != NULL);
  47. DBGPRINTF( ( DBG_CONTEXT,
  48. "Printing Oid %s = %08x. Length = %u.\n",
  49. pszOidDescription,
  50. pAsno, len));
  51. for(i = 0; i < len; i++) {
  52. DBGPRINTF( ( DBG_CONTEXT,
  53. "AsnOid[ %u] = %u\n",
  54. i, pAsno->ids[i]));
  55. }
  56. # endif // DBG
  57. return;
  58. } // PrintAsnObjectIdentifier()
  59. /************************************************************
  60. * Functions
  61. ************************************************************/
  62. UINT
  63. ResolveVarBinding(
  64. IN OUT RFC1157VarBind * pRfcVarBinding,
  65. IN BYTE pduAction,
  66. IN LPVOID pStatistics,
  67. IN LPMIB_ENTRIES pMibEntries
  68. )
  69. /*++
  70. Description:
  71. This function resolves a single variable binding. Modifies the variable
  72. on a GET or a GET-NEXT.
  73. Arguments:
  74. pRfcVarBinding pointer to RFC Variable Bindings
  75. pduAction Protocol Data Unit Action specified.
  76. pStatistics pointer to statisitcs data structure containing
  77. values of counter data.
  78. pMibEntries pointer to MIB_ENTRIES context information
  79. which contains prefix, array of MIB_ENTRIES and
  80. count of the entries.
  81. Returns:
  82. Standard PDU error codes.
  83. Note:
  84. --*/
  85. {
  86. AsnObjectIdentifier AsnTempOid;
  87. LPMIB_ENTRY pMibScan;
  88. UINT pduResult = SNMP_ERRORSTATUS_NOERROR;
  89. LPMIB_ENTRY pMibUpperBound =
  90. pMibEntries->prgMibEntry + pMibEntries->cMibEntries;
  91. //
  92. // Search for the variable binding name in the mib.
  93. //
  94. IF_DEBUG( SNMP_RESOLVE) {
  95. DBGPRINTF( ( DBG_CONTEXT,
  96. " ResolveVarBinding( Var=%08x, Action=%x) called.\n",
  97. pRfcVarBinding, pduAction));
  98. PrintAsnObjectIdentifier( " Variable to Resolve",
  99. &pRfcVarBinding->name);
  100. }
  101. for( pMibScan = pMibEntries->prgMibEntry;
  102. pMibScan < pMibUpperBound;
  103. pMibScan++) {
  104. int iCmpResult;
  105. //
  106. // Create a fully qualified OID for the current item in the MIB.
  107. // and use it for comparing against variable to be resolved.
  108. //
  109. SNMP_oidcpy( &AsnTempOid, pMibEntries->pOidPrefix);
  110. SNMP_oidappend( &AsnTempOid, &pMibScan->asnOid);
  111. iCmpResult = SNMP_oidcmp( &pRfcVarBinding->name, &AsnTempOid);
  112. SNMP_oidfree( &AsnTempOid);
  113. IF_DEBUG( SNMP_RESOLVE) {
  114. DBGPRINTF( ( DBG_CONTEXT,
  115. " Comparing with suffix Oid %08x yields %d\n",
  116. &pMibScan->asnOid, iCmpResult));
  117. PrintAsnObjectIdentifier( " StatisticsSuffix",
  118. &pMibScan->asnOid);
  119. }
  120. if ( iCmpResult == 0) {
  121. //
  122. // Found a match. Stop the search and process.
  123. //
  124. break;
  125. } else
  126. if ( iCmpResult < 0) {
  127. //
  128. // This could be the OID of a leaf ( withoug a trailing 0) or
  129. // it could contain an invalid OID ( between valid OIDs).
  130. //
  131. if ( pduAction == MIB_GETNEXT) {
  132. //
  133. // Advance the variable binding to next entry
  134. //
  135. SNMP_oidfree( &pRfcVarBinding->name);
  136. SNMP_oidcpy( &pRfcVarBinding->name,
  137. pMibEntries->pOidPrefix);
  138. SNMP_oidappend( &pRfcVarBinding->name, &pMibScan->asnOid);
  139. if ( ( pMibScan->bType != ASN_RFC1155_OPAQUE) &&
  140. ( pMibScan->bType != ASN_SEQUENCE)) {
  141. pduAction = MIB_GET;
  142. }
  143. } else {
  144. pduResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  145. }
  146. //
  147. // Stop and process the appropriate entry.
  148. //
  149. break;
  150. } // ( iCmpResult < 0)
  151. } // for
  152. if ( pMibScan >= pMibUpperBound) {
  153. pduResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  154. }
  155. if ( pduResult == SNMP_ERRORSTATUS_NOERROR) {
  156. //
  157. // A match is found or further processing is required.
  158. //
  159. DBG_ASSERT( pMibScan < pMibUpperBound);
  160. if ( pMibScan->pMibFunc == NULL) {
  161. //
  162. // This happens only if the match is for Group OID
  163. //
  164. pduResult = ( ( pduAction != MIB_GETNEXT) ?
  165. SNMP_ERRORSTATUS_NOSUCHNAME:
  166. MibGetNextVar( pRfcVarBinding,
  167. pMibScan,
  168. pMibEntries,
  169. pStatistics));
  170. } else {
  171. pduResult = ( pMibScan->pMibFunc) ( pRfcVarBinding,
  172. pduAction,
  173. pMibScan,
  174. pMibEntries,
  175. pStatistics);
  176. }
  177. }
  178. IF_DEBUG( SNMP_RESOLVE) {
  179. DBGPRINTF( ( DBG_CONTEXT,
  180. " ResolveVarBinding returns %u.\n",
  181. pduResult));
  182. }
  183. return ( pduResult);
  184. } // ResolveVarBinding()
  185. UINT
  186. MibStatisticsWorker(
  187. IN OUT RFC1157VarBind * pRfcVarBinding,
  188. IN UINT pduAction,
  189. IN struct _MIB_ENTRY * pMibeCurrent,
  190. IN struct _MIB_ENTRIES * pMibEntries,
  191. IN LPVOID pStatistics
  192. )
  193. /*++
  194. This function resolves the variables assuming that there is statistical
  195. information ( sequence of counters) in the data passed in pStatistics.
  196. Arguments:
  197. pRfcVarBind pointer to RFC variable binding to be resolved.
  198. pduAction protocol data unit action to be taken.
  199. pMibeCurrent pointer to MIB_ENTRY which is o be used for resolution.
  200. pMibEntries pointer to MIB_ENTRIES structure to be used
  201. as context for resolving and performing the action.
  202. pStatistics pointer to sequence of counters used for data resolution.
  203. Returns:
  204. Standard PDU error codes.
  205. --*/
  206. {
  207. UINT pduResult = SNMP_ERRORSTATUS_NOERROR;
  208. // default indicating action to be done at end of switch
  209. switch( pduAction) {
  210. case MIB_SET:
  211. case MIB_GETNEXT:
  212. // action is performed at the end of switch statement.
  213. break;
  214. case MIB_GETFIRST:
  215. case MIB_GET:
  216. //
  217. // If no statistics do no action.
  218. // If this is the header field ( non-leaf) do no action
  219. // Otherwise, perform action as if this is the leaf node.
  220. //
  221. if ( pStatistics == NULL || pMibeCurrent->lFieldOffset == -1) {
  222. pduResult = SNMP_ERRORSTATUS_GENERR;
  223. }
  224. // Action on this node is performed at the end of the switch statement.
  225. break;
  226. default:
  227. pduResult = SNMP_ERRORSTATUS_GENERR;
  228. break;
  229. } // switch()
  230. if ( pduResult == SNMP_ERRORSTATUS_NOERROR) {
  231. //
  232. // Use the generic leaf function to perform the action specified.
  233. //
  234. pduResult = MibLeafFunction( pRfcVarBinding, pduAction, pMibeCurrent,
  235. pMibEntries, pStatistics);
  236. }
  237. return ( pduResult);
  238. } // MibStatisticsWorker()
  239. static UINT
  240. MibLeafFunction(
  241. IN OUT RFC1157VarBind * pRfcVarBinding,
  242. IN UINT pduAction,
  243. IN struct _MIB_ENTRY * pMibeCurrent,
  244. IN struct _MIB_ENTRIES * pMibEntries,
  245. IN LPVOID pStatistics
  246. )
  247. /*++
  248. This function resolves the variables assuming that there is statistical
  249. information ( sequence of counters) in the data passed in pStatistics
  250. and that this is a leaf node of the MIB tree.
  251. This is a generic function for leaf nodes.
  252. Arguments:
  253. pRfcVarBind pointer to RFC variable binding to be resolved.
  254. pduAction protocol data unit action to be taken.
  255. pMibeCurrent pointer to MIB_ENTRY which is o be used for resolution.
  256. pMibEntries pointer to MIB_ENTRIES structure to be used
  257. as context for resolving and performing the action.
  258. pStatistics pointer to sequence of counters used for data resolution.
  259. Returns:
  260. Standard PDU error codes.
  261. --*/
  262. {
  263. UINT pduResult = SNMP_ERRORSTATUS_NOSUCHNAME; // default is error value.
  264. switch( pduAction ) {
  265. case MIB_GETNEXT:
  266. //
  267. // Determine if we're within the range and not at the end.
  268. // If not within the range the above default pduResult == NOSUCHNAME
  269. // is the required error message.
  270. //
  271. if ( ( pMibeCurrent >= pMibEntries->prgMibEntry) &&
  272. ( pMibeCurrent <
  273. ( pMibEntries->prgMibEntry + pMibEntries->cMibEntries))) {
  274. pduResult = MibGetNextVar( pRfcVarBinding,
  275. pMibeCurrent,
  276. pMibEntries,
  277. pStatistics);
  278. }
  279. break;
  280. case MIB_GETFIRST:
  281. case MIB_GET:
  282. //
  283. // Make sure that this variable's ACCESS is GET'able.
  284. // If the access prohibits from GETting it, report error as
  285. // NOSUCHNAME ( default value of pduResult in initialization above)
  286. //
  287. if(( pMibeCurrent->uiAccess == MIB_ACCESS_READ ) ||
  288. ( pMibeCurrent->uiAccess == MIB_ACCESS_READWRITE ) ) {
  289. DWORD dwValue;
  290. //
  291. // Setup pRfcVarBinding's return value.
  292. //
  293. DBG_ASSERT( pStatistics != NULL);
  294. pRfcVarBinding->value.asnType = pMibeCurrent->bType;
  295. dwValue = *( (LPDWORD )((LPBYTE )pStatistics +
  296. pMibeCurrent->lFieldOffset));
  297. pduResult = SNMP_ERRORSTATUS_NOERROR; // we found a value.
  298. switch( pMibeCurrent->bType) {
  299. case ASN_RFC1155_GAUGE:
  300. pRfcVarBinding->value.asnValue.gauge = (AsnGauge ) dwValue;
  301. break;
  302. case ASN_RFC1155_COUNTER:
  303. pRfcVarBinding->value.asnValue.counter = (AsnCounter ) dwValue;
  304. break;
  305. case ASN_INTEGER:
  306. pRfcVarBinding->value.asnValue.number = (AsnInteger ) dwValue;
  307. break;
  308. case ASN_RFC1155_IPADDRESS:
  309. case ASN_OCTETSTRING:
  310. //
  311. // Not supported for this MIB (yet).
  312. // Fall through to indicate generic error.
  313. //
  314. default:
  315. //
  316. // Sorry! Type in Mibe does not suit our purpose.
  317. // Indicate generic error.
  318. //
  319. pduResult = SNMP_ERRORSTATUS_GENERR;
  320. break;
  321. } // innner switch
  322. } // if ( valid read access)
  323. break;
  324. case MIB_SET:
  325. //
  326. // We don't support settable variables (yet).
  327. // Fall through for error.
  328. //
  329. default:
  330. pduResult = SNMP_ERRORSTATUS_GENERR;
  331. break;
  332. } // switch ( pduAction)
  333. return ( pduResult);
  334. } // MibLeafFunction()
  335. static UINT
  336. MibGetNextVar(
  337. IN OUT RFC1157VarBind * pRfcVarBinding,
  338. IN MIB_ENTRY * pMibeCurrent,
  339. IN MIB_ENTRIES * pMibEntries,
  340. IN LPVOID pStatistics)
  341. /*++
  342. Description:
  343. This function sets the binding variable to iterate to the next variable.
  344. Arguments:
  345. pRfcVarBind pointer to RFC variable binding to be resolved.
  346. pMibeCurrent pointer to MIB_ENTRY which is o be used for resolution.
  347. pMibEntries pointer to MIB_ENTRIES structure to be used
  348. as context for resolving and performing the action.
  349. pStatistics pointer to sequence of counters used for data resolution.
  350. Returns:
  351. PDU Error Codes.
  352. --*/
  353. {
  354. UINT pduResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  355. LPMIB_ENTRY pMibUpperBound =
  356. pMibEntries->prgMibEntry + pMibEntries->cMibEntries;
  357. //
  358. // If within the range of MIB ENTRIES process.
  359. //
  360. if ( pMibeCurrent >= pMibEntries->prgMibEntry) {
  361. //
  362. // Scan through the remaining MIB Entries
  363. //
  364. LPMIB_ENTRY pMibeScan;
  365. for( pMibeScan = pMibeCurrent+1;
  366. pMibeScan < pMibUpperBound;
  367. pMibeScan++ ) {
  368. //
  369. // Setup variable bindings for the next MIB variable
  370. //
  371. SNMP_oidfree( &pRfcVarBinding->name);
  372. SNMP_oidcpy( &pRfcVarBinding->name, pMibEntries->pOidPrefix);
  373. SNMP_oidappend( &pRfcVarBinding->name, &pMibeScan->asnOid);
  374. //
  375. // If the function pointer is not NULL and the type of the MIB
  376. // variable is anything but OPAQUE, then call the function to
  377. // process the MIB variable.
  378. //
  379. if(( pMibeScan->pMibFunc != NULL ) &&
  380. ( pMibeScan->bType != ASN_RFC1155_OPAQUE ) ) {
  381. pduResult = ( pMibeScan->pMibFunc)( pRfcVarBinding,
  382. MIB_GETFIRST,
  383. pMibeScan,
  384. pMibEntries,
  385. pStatistics);
  386. break;
  387. }
  388. //
  389. // On failure in the scan, pduResult will have default value
  390. // as initialized above in declaration.
  391. //
  392. } // for
  393. }
  394. return ( pduResult);
  395. } // MibGetNextVar()
  396. /************************ End of File ***********************/