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.

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