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.

677 lines
18 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. oidconv.c
  5. Abstract:
  6. Routines to manage conversions between OID descriptions and numerical OIDs.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 10-May-1996 DonRyan
  11. Removed banner from Technology Dynamics, Inc.
  12. --*/
  13. //--------------------------- WINDOWS DEPENDENCIES --------------------------
  14. #include <windows.h>
  15. //--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
  16. #include <ctype.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <snmp.h>
  21. #include <snmputil.h>
  22. //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
  23. //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
  24. #include "oidconv.h"
  25. //--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
  26. /* name to used when converting OID <--> TEXT */
  27. LPSTR lpInputFileName = "mib.bin";
  28. //--------------------------- PRIVATE CONSTANTS -----------------------------
  29. #define FILENODE_SIZE sizeof(T_FILE_NODE)
  30. #define OID_PREFIX_LEN (sizeof MIB_Prefix / sizeof(UINT))
  31. #define STR_PREFIX_LEN (strlen(MIB_StrPrefix))
  32. #define SEEK_SET 0
  33. #define SEEK_CUR 1
  34. //--------------------------- PRIVATE STRUCTS -------------------------------
  35. //****************************************************************
  36. //
  37. // Record structure in file
  38. //
  39. // These are the necessary fields to process a conversion request.
  40. // When a request is made, the MIB file is searched sequentially
  41. // matching subid's. The field, lNextOffset, is an offset from the
  42. // current file position to the current nodes next sibling.
  43. //
  44. // The text subid for each node is stored directly after the
  45. // T_FILE_NODE structure in the file. Its length is stored in the
  46. // field, uStrLen.
  47. //
  48. // This is done because there are no limits placed on the size
  49. // of a text subid. Hence, when the T_FILE_NODE structure is
  50. // read from the MIB file, the field, lpszTextSubID is not valid.
  51. // The field will eventually point to the storage allocated to
  52. // hold the text subid.
  53. //
  54. // The order of the nodes in the file is the same as if the MIB
  55. // tree was traversed in a "pre-order" manner.
  56. //
  57. //****************************************************************
  58. typedef struct _FileNode {
  59. long lNextOffset; // This field must remain first
  60. UINT uNumChildren;
  61. UINT uStrLen;
  62. LPSTR lpszTextSubID;
  63. UINT uNumSubID;
  64. } T_FILE_NODE;
  65. // mib.bin file actually has the following platform independent format
  66. // on 32bit(x86) and 64bit(ia64) environment. See Bug# 125494 for detail.
  67. typedef struct _FileNodeEx {
  68. long lNextOffset; // This field must remain first
  69. UINT uNumChildren;
  70. UINT uStrLen;
  71. UINT uReserved;
  72. UINT uNumSubID;
  73. } T_FILE_NODE_EX;
  74. #define FILENODE_SIZE_EX sizeof(T_FILE_NODE_EX)
  75. //--------------------------- PRIVATE VARIABLES -----------------------------
  76. LPSTR MIB_StrPrefix = "iso.org.dod.internet.mgmt.mib-2";
  77. UINT MIB_Prefix[] = { 1, 3, 6, 1, 2, 1 };
  78. AsnObjectIdentifier MIB_OidPrefix = { OID_PREFIX_LEN, MIB_Prefix };
  79. //--------------------------- PRIVATE PROTOTYPES ----------------------------
  80. //--------------------------- PRIVATE PROCEDURES ----------------------------
  81. //
  82. // GetNextNode
  83. // Reads the next record from MIB file into a FILENODE structure.
  84. //
  85. // Notes:
  86. //
  87. // Return Codes:
  88. // SNMPAPI_NOERROR
  89. // SNMPAPI_ERROR
  90. //
  91. // Error Codes:
  92. // None.
  93. //
  94. SNMPAPI GetNextNode(
  95. IN HFILE fh,
  96. OUT T_FILE_NODE * Node
  97. )
  98. {
  99. SNMPAPI nResult;
  100. T_FILE_NODE_EX NodeEx;
  101. ZeroMemory(&NodeEx, FILENODE_SIZE_EX);
  102. Node->lpszTextSubID = NULL;
  103. // Read in node
  104. if ( FILENODE_SIZE_EX != _lread(fh, (LPSTR)(&NodeEx), FILENODE_SIZE_EX) )
  105. {
  106. nResult = SNMPAPI_ERROR;
  107. goto Exit;
  108. }
  109. // Convert node format from mib.bin to format in memory
  110. // The format in the file is independent of 32bit(x86)/64bit(ia64)
  111. // architecture.
  112. Node->lNextOffset = NodeEx.lNextOffset;
  113. Node->uNumChildren = NodeEx.uNumChildren;
  114. Node->uNumSubID = NodeEx.uNumSubID;
  115. Node->uStrLen = NodeEx.uStrLen;
  116. // Alloc space for string
  117. if ( NULL ==
  118. (Node->lpszTextSubID = SnmpUtilMemAlloc((1+Node->uStrLen) * sizeof(char))) )
  119. {
  120. nResult = SNMPAPI_ERROR;
  121. goto Exit;
  122. }
  123. // Read in subid string
  124. if ( Node->uStrLen != _lread(fh, Node->lpszTextSubID, Node->uStrLen) )
  125. {
  126. nResult = SNMPAPI_ERROR;
  127. goto Exit;
  128. }
  129. // NULL terminate the text sub id
  130. Node->lpszTextSubID[Node->uStrLen] = '\0';
  131. nResult = SNMPAPI_NOERROR;
  132. Exit:
  133. if ( SNMPAPI_ERROR == nResult )
  134. {
  135. SnmpUtilMemFree( Node->lpszTextSubID );
  136. Node->lpszTextSubID = NULL; // prevent memory being double freed
  137. }
  138. return nResult;
  139. } // GetNextNode
  140. //
  141. // SkipSubTree
  142. // Frees a FILENODE and all information contained in it.
  143. //
  144. // Notes:
  145. //
  146. // Return Codes:
  147. //
  148. // Error Codes:
  149. // None.
  150. //
  151. SNMPAPI SkipSubTree(
  152. IN HFILE fh,
  153. IN T_FILE_NODE *Node
  154. )
  155. {
  156. SNMPAPI nResult;
  157. // Skip entire subtree
  158. if ( HFILE_ERROR == _llseek(fh, Node->lNextOffset, SEEK_CUR) )
  159. {
  160. nResult = SNMPAPI_ERROR;
  161. goto Exit;
  162. }
  163. nResult = SNMPAPI_NOERROR;
  164. Exit:
  165. return nResult;
  166. } // SkipSubTree
  167. //--------------------------- PUBLIC PROCEDURES -----------------------------
  168. //
  169. // SnmpMgrOid2Text
  170. // Converts an OID to its textual description.
  171. //
  172. // Notes:
  173. //
  174. // Return Codes:
  175. // SNMPAPI_NOERROR
  176. // SNMPAPI_ERROR
  177. //
  178. // Error Codes:
  179. // None.
  180. //
  181. SNMPAPI SnmpMgrOid2Text(
  182. IN AsnObjectIdentifier *Oid, // Pointer to OID to convert
  183. OUT LPSTR *lpszTextOid // Resulting text OID
  184. )
  185. {
  186. T_FILE_NODE Node;
  187. OFSTRUCT of;
  188. HFILE fh;
  189. UINT Siblings;
  190. UINT OidSubId;
  191. UINT uTxtOidLen;
  192. BOOL bFound;
  193. BOOL bPartial;
  194. BOOL bDot;
  195. SNMPAPI nResult;
  196. LPSTR pszTmpTextOid;
  197. // OPENISSUE - this code does not generate errors if subid 0 is embeded
  198. // OPENISSUE - opening file every time could be a performance issue
  199. // OPENISSUE - optimization of file access could improve performance
  200. *lpszTextOid = NULL;
  201. // Open file and check for errors
  202. if ( HFILE_ERROR == (fh = OpenFile(lpInputFileName, &of, OF_READ|OF_SHARE_DENY_WRITE)) )
  203. {
  204. nResult = SNMPAPI_ERROR;
  205. goto Exit;
  206. }
  207. // Test for MIB prefix
  208. bDot = !( bPartial = OID_PREFIX_LEN < Oid->idLength &&
  209. !SnmpUtilOidNCmp(Oid, &MIB_OidPrefix, OID_PREFIX_LEN) );
  210. // Loop until conversion is finished
  211. OidSubId = 0;
  212. uTxtOidLen = 0;
  213. Node.uNumChildren = 1;
  214. Node.lpszTextSubID = NULL;
  215. while ( OidSubId < Oid->idLength )
  216. {
  217. // Init to not found on this level
  218. bFound = FALSE;
  219. Siblings = Node.uNumChildren;
  220. // While there are siblings and the sub id is not found keep looking
  221. while ( Siblings && !bFound )
  222. {
  223. Node.lpszTextSubID = NULL;
  224. // Get next node from mib.bin file
  225. if ( SNMPAPI_ERROR == GetNextNode(fh, &Node) )
  226. {
  227. nResult = SNMPAPI_ERROR;
  228. goto Exit;
  229. }
  230. Siblings --;
  231. // Compare the numeric subid's
  232. if ( Oid->ids[OidSubId] == Node.uNumSubID )
  233. {
  234. bFound = TRUE;
  235. // If OID is a partial, then skip prefix subid's
  236. if ( OidSubId >= OID_PREFIX_LEN || !bPartial )
  237. {
  238. // Realloc space for text id - add 2 for '.' and NULL terminator
  239. if ( NULL == (pszTmpTextOid =
  240. (LPSTR) SnmpUtilMemReAlloc(*lpszTextOid,
  241. (uTxtOidLen+Node.uStrLen+2) * sizeof(char))) )
  242. {
  243. SnmpUtilMemFree( Node.lpszTextSubID );
  244. nResult = SNMPAPI_ERROR;
  245. goto Exit;
  246. }
  247. *lpszTextOid = pszTmpTextOid;
  248. // Add DOT separator
  249. if ( bDot )
  250. {
  251. (*lpszTextOid)[uTxtOidLen] = '.';
  252. // Save text subid
  253. memcpy( &(*lpszTextOid)[uTxtOidLen+1],
  254. Node.lpszTextSubID, Node.uStrLen+1 );
  255. // Update length of text oid - add one for separator
  256. uTxtOidLen += Node.uStrLen + 1;
  257. }
  258. else
  259. {
  260. bDot = TRUE;
  261. // Save text subid
  262. memcpy( &(*lpszTextOid)[uTxtOidLen],
  263. Node.lpszTextSubID, Node.uStrLen+1 );
  264. // Update length of text oid
  265. uTxtOidLen += Node.uStrLen;
  266. }
  267. }
  268. // try to convert the next OID subid
  269. OidSubId ++;
  270. }
  271. else
  272. {
  273. // Skip over subtree since not a match
  274. if ( SNMPAPI_ERROR == SkipSubTree(fh, &Node) )
  275. {
  276. SnmpUtilMemFree( Node.lpszTextSubID );
  277. nResult = SNMPAPI_ERROR;
  278. goto Exit;
  279. }
  280. }
  281. // Free the text sub id read
  282. SnmpUtilMemFree( Node.lpszTextSubID );
  283. Node.lpszTextSubID = NULL;
  284. } // while
  285. // If no sub id matches
  286. if ( !bFound )
  287. {
  288. break;
  289. }
  290. } // while
  291. // Make sure that the entire OID was converted
  292. while ( OidSubId < Oid->idLength )
  293. {
  294. char NumChar[100];
  295. // in case _itoa fails, we won't get garbage
  296. ZeroMemory(NumChar, sizeof(NumChar));
  297. _itoa( Oid->ids[OidSubId], NumChar, 10 );
  298. // Realloc space for text id - add 2 for '.' and NULL terminator
  299. if ( NULL ==
  300. (pszTmpTextOid = (LPSTR) SnmpUtilMemReAlloc(*lpszTextOid,
  301. (uTxtOidLen+strlen(NumChar)+4) * sizeof(char))) )
  302. {
  303. nResult = SNMPAPI_ERROR;
  304. goto Exit;
  305. }
  306. *lpszTextOid = pszTmpTextOid;
  307. // Add DOT separator
  308. (*lpszTextOid)[uTxtOidLen] = '.';
  309. // Save text subid
  310. memcpy( &(*lpszTextOid)[uTxtOidLen+1], NumChar, strlen(NumChar)+1 );
  311. // Skip to next OID subid
  312. OidSubId ++;
  313. // Update length of text oid - add one for separator
  314. uTxtOidLen += strlen(NumChar) + 1;
  315. } // while
  316. nResult = SNMPAPI_NOERROR;
  317. Exit:
  318. if ( HFILE_ERROR != fh )
  319. {
  320. _lclose( fh );
  321. }
  322. if ( SNMPAPI_ERROR == nResult )
  323. {
  324. SnmpUtilMemFree( *lpszTextOid );
  325. *lpszTextOid = NULL;
  326. }
  327. return nResult;
  328. } // SnmpMgrOid2Text
  329. //
  330. // SnmpMgrText2Oid
  331. // Converts an OID text description to its numerical equivalent.
  332. //
  333. // Notes:
  334. //
  335. // Return Codes:
  336. // SNMPAPI_NOERROR
  337. // SNMPAPI_ERROR
  338. //
  339. // Error Codes:
  340. // None.
  341. //
  342. SNMPAPI SnmpMgrText2Oid(
  343. IN LPSTR lpszTextOid, // Pointer to text OID to convert
  344. IN OUT AsnObjectIdentifier *Oid // Resulting numeric OID
  345. )
  346. {
  347. #define DELIMETERS ".\0"
  348. T_FILE_NODE Node;
  349. OFSTRUCT of;
  350. HFILE fh;
  351. UINT Siblings;
  352. LPSTR lpszSubId;
  353. LPSTR lpszWrkOid = NULL;
  354. BOOL bFound;
  355. UINT uSubId;
  356. SNMPAPI nResult;
  357. UINT * idsTmp;
  358. // OPENISSUE - this code does not generate errors if subid 0 is embeded
  359. // OPENISSUE - opening file every time could be a performance issue
  360. // OPENISSUE - optimization of file access could improve performance
  361. // Init. OID structure
  362. Oid->idLength = 0;
  363. Oid->ids = NULL;
  364. // check for null string and empty string
  365. if ( NULL == lpszTextOid || '\0' == lpszTextOid[0] )
  366. {
  367. fh = HFILE_ERROR;
  368. nResult = SNMPAPI_NOERROR;
  369. goto Exit;
  370. }
  371. // Open file and check for errors
  372. if ( HFILE_ERROR == (fh = OpenFile(lpInputFileName, &of, OF_READ|OF_SHARE_DENY_WRITE)) )
  373. {
  374. nResult = SNMPAPI_ERROR;
  375. goto Exit;
  376. }
  377. // Make working copy of string
  378. if ( ('.' == lpszTextOid[0]) )
  379. {
  380. if ( NULL == (lpszWrkOid = SnmpUtilMemAlloc((strlen(lpszTextOid)+1) * sizeof(char))) )
  381. {
  382. nResult = SNMPAPI_ERROR;
  383. goto Exit;
  384. }
  385. strcpy( lpszWrkOid, lpszTextOid+1 );
  386. }
  387. else
  388. {
  389. if ( NULL ==
  390. (lpszWrkOid =
  391. SnmpUtilMemAlloc((strlen(lpszTextOid)+STR_PREFIX_LEN+1+1) * sizeof(char))) )
  392. {
  393. nResult = SNMPAPI_ERROR;
  394. goto Exit;
  395. }
  396. strcpy( lpszWrkOid, MIB_StrPrefix );
  397. lpszWrkOid[STR_PREFIX_LEN] = '.';
  398. strcpy( &lpszWrkOid[STR_PREFIX_LEN+1], lpszTextOid );
  399. }
  400. Node.uNumChildren = 1;
  401. Node.lpszTextSubID = NULL;
  402. lpszSubId = strtok( lpszWrkOid, DELIMETERS );
  403. // Loop until conversion is finished
  404. while ( NULL != lpszSubId )
  405. {
  406. // Init to not found on this level
  407. bFound = FALSE;
  408. Siblings = Node.uNumChildren;
  409. // Check for imbedded numbers
  410. if ( isdigit(*lpszSubId) )
  411. {
  412. UINT I;
  413. // Make sure this is a NUMBER without alpha's
  414. for ( I=0;I < strlen(lpszSubId);I++ )
  415. {
  416. if ( !isdigit(lpszSubId[I]) )
  417. {
  418. nResult = SNMPAPI_ERROR;
  419. goto Exit;
  420. }
  421. }
  422. uSubId = atoi( lpszSubId );
  423. }
  424. else
  425. {
  426. uSubId = 0;
  427. }
  428. // While there are siblings and the sub id is not found keep looking
  429. while ( Siblings && !bFound )
  430. {
  431. // Get next sibling
  432. if ( SNMPAPI_ERROR == GetNextNode(fh, &Node) )
  433. {
  434. nResult = SNMPAPI_ERROR;
  435. goto Exit;
  436. }
  437. Siblings --;
  438. if ( uSubId )
  439. {
  440. // Compare the numeric subid's
  441. if ( Node.uNumSubID == uSubId )
  442. {
  443. bFound = TRUE;
  444. // Add space for new sub id
  445. if ( NULL ==
  446. (idsTmp =
  447. (UINT*) SnmpUtilMemReAlloc(Oid->ids, (Oid->idLength+1) * sizeof(UINT))) )
  448. {
  449. SnmpUtilMemFree( Node.lpszTextSubID );
  450. nResult = SNMPAPI_ERROR;
  451. goto Exit;
  452. }
  453. Oid->ids = idsTmp;
  454. // Append this sub id to end of numeric OID
  455. Oid->ids[Oid->idLength++] = Node.uNumSubID;
  456. }
  457. }
  458. else
  459. {
  460. // Compare the text subid's
  461. if ( !strcmp(lpszSubId, Node.lpszTextSubID) )
  462. {
  463. bFound = TRUE;
  464. // Add space for new sub id
  465. if ( NULL ==
  466. (idsTmp =
  467. (UINT*) SnmpUtilMemReAlloc(Oid->ids, (Oid->idLength+1) * sizeof(UINT))) )
  468. {
  469. SnmpUtilMemFree( Node.lpszTextSubID );
  470. nResult = SNMPAPI_ERROR;
  471. goto Exit;
  472. }
  473. Oid->ids = idsTmp;
  474. // Append this sub id to end of numeric OID
  475. Oid->ids[Oid->idLength++] = Node.uNumSubID;
  476. }
  477. }
  478. // Skip over subtree since not a match
  479. if ( !bFound && SNMPAPI_ERROR == SkipSubTree(fh, &Node) )
  480. {
  481. SnmpUtilMemFree( Node.lpszTextSubID );
  482. nResult = SNMPAPI_ERROR;
  483. goto Exit;
  484. }
  485. // Free the text sub id read
  486. SnmpUtilMemFree( Node.lpszTextSubID );
  487. Node.lpszTextSubID = NULL;
  488. } // while
  489. // If no sub id matches
  490. if ( !bFound )
  491. {
  492. break;
  493. }
  494. // Advance to next sub id
  495. lpszSubId = strtok( NULL, DELIMETERS );
  496. } // while
  497. // Make sure that the entire OID was converted
  498. while ( NULL != lpszSubId )
  499. {
  500. UINT I;
  501. // Make sure this is a NUMBER without alpha's
  502. for ( I=0;I < strlen(lpszSubId);I++ )
  503. {
  504. if ( !isdigit(lpszSubId[I]) )
  505. {
  506. nResult = SNMPAPI_ERROR;
  507. goto Exit;
  508. }
  509. }
  510. // Add space for new sub id
  511. if ( NULL ==
  512. (idsTmp = (UINT*) SnmpUtilMemReAlloc(Oid->ids,
  513. (Oid->idLength+1) * sizeof(UINT))) )
  514. {
  515. nResult = SNMPAPI_ERROR;
  516. goto Exit;
  517. }
  518. Oid->ids = idsTmp;
  519. // Append this sub id to end of numeric OID
  520. Oid->ids[Oid->idLength++] = atoi( lpszSubId );
  521. // Advance to next sub id
  522. lpszSubId = strtok( NULL, DELIMETERS );
  523. } // while
  524. // it is illegal for an oid to be less than two subidentifiers
  525. if (Oid->idLength < 2)
  526. {
  527. nResult = SNMPAPI_ERROR;
  528. goto Exit;
  529. }
  530. nResult = SNMPAPI_NOERROR;
  531. Exit:
  532. if ( HFILE_ERROR != fh )
  533. {
  534. _lclose( fh );
  535. }
  536. if ( SNMPAPI_ERROR == nResult )
  537. {
  538. SnmpUtilOidFree( Oid );
  539. }
  540. if ( NULL != lpszWrkOid )
  541. {
  542. SnmpUtilMemFree ( lpszWrkOid );
  543. }
  544. return nResult;
  545. } // SnmpMgrText2Oid
  546. //------------------------------- END ---------------------------------------