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.

4103 lines
108 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. snmptfx.c
  5. Abstract:
  6. Provides common varbind resolution functionality for subagents.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 02-Oct-1996 DonRyan
  11. Moved from extensible agent in anticipation of SNMPv2 SPI.
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h> // using ntrtl's ASSERT
  21. #include <snmp.h>
  22. #include <snmputil.h>
  23. #include <snmpexts.h>
  24. #include <winsock.h>
  25. #define HASH_TABLE_SIZE 101
  26. #define HASH_TABLE_RADIX 18
  27. #define INVALID_INDEX ((DWORD)(-1))
  28. ///////////////////////////////////////////////////////////////////////////////
  29. // //
  30. // Private type definitions //
  31. // //
  32. ///////////////////////////////////////////////////////////////////////////////
  33. typedef struct _SnmpVarBindXlat {
  34. UINT vlIndex; // index into view list
  35. UINT vblIndex; // index into varbind list
  36. SnmpMibEntry * mibEntry; // pointer to mib information
  37. struct _SnmpExtQuery * extQuery; // pointer to followup query
  38. } SnmpVarBindXlat;
  39. typedef struct _SnmpGenericList {
  40. VOID * data; // context-specific pointer
  41. UINT len; // context-specific length
  42. } SnmpGenericList;
  43. typedef struct _SnmpTableXlat {
  44. AsnObjectIdentifier txOid; // table index oid
  45. SnmpMibTable * txInfo; // table description
  46. UINT txIndex; // index into table list
  47. } SnmpTableXlat;
  48. typedef struct _SnmpExtQuery {
  49. UINT mibAction; // type of query
  50. UINT viewType; // type of view
  51. UINT vblNum; // number of varbinds
  52. SnmpVarBindXlat * vblXlat; // info to reorder varbinds
  53. SnmpTableXlat * tblXlat; // info to parse table oids
  54. SnmpGenericList extData; // context-specific buffer
  55. FARPROC extFunc; // instrumentation callback
  56. } SnmpExtQuery;
  57. #define INVALID_QUERY ((SnmpExtQuery*)(-1))
  58. typedef struct _SnmpExtQueryList {
  59. SnmpExtQuery * query; // list of subagent queries
  60. UINT len; // number of queries in list
  61. UINT action; // original query request
  62. } SnmpExtQueryList;
  63. typedef struct _SnmpHashNode {
  64. SnmpMibEntry * mibEntry;
  65. struct _SnmpHashNode * nextEntry;
  66. } SnmpHashNode;
  67. typedef struct _SnmpTfxView {
  68. SnmpMibView * mibView;
  69. SnmpHashNode ** hashTable;
  70. } SnmpTfxView;
  71. typedef struct _SnmpTfxInfo {
  72. UINT numViews;
  73. SnmpTfxView * tfxViews;
  74. } SnmpTfxInfo;
  75. ///////////////////////////////////////////////////////////////////////////////
  76. // //
  77. // Private prototypes //
  78. // //
  79. ///////////////////////////////////////////////////////////////////////////////
  80. VOID
  81. ValidateQueryList(
  82. SnmpTfxInfo * tfxInfo,
  83. SnmpExtQueryList * ql,
  84. UINT q,
  85. RFC1157VarBindList * vbl,
  86. UINT * errorStatus,
  87. UINT * errorIndex
  88. );
  89. ///////////////////////////////////////////////////////////////////////////////
  90. // //
  91. // Private procedures //
  92. // //
  93. ///////////////////////////////////////////////////////////////////////////////
  94. UINT
  95. OidToHashTableIndex(
  96. AsnObjectIdentifier * hashOid
  97. )
  98. /*++
  99. Routine Description:
  100. Hash function for mib entry access.
  101. Arguments:
  102. hashOid - object identifer to hash into table position.
  103. Return Values:
  104. Returns hash table position.
  105. --*/
  106. {
  107. UINT i;
  108. UINT j;
  109. // process each element of the oid
  110. for (i=0, j=0; i < hashOid->idLength; i++) {
  111. // determine table position by summing oid
  112. j = (j * HASH_TABLE_RADIX) + hashOid->ids[i];
  113. }
  114. // adjust to within table
  115. return (j % HASH_TABLE_SIZE);
  116. }
  117. VOID
  118. FreeHashTable(
  119. SnmpHashNode ** hashTable
  120. )
  121. /*++
  122. Routine Description:
  123. Destroys hash table used for accessing views.
  124. Arguments:
  125. hashTable - table of hash nodes.
  126. Return Values:
  127. None.
  128. --*/
  129. {
  130. UINT i;
  131. SnmpHashNode * nextNode;
  132. SnmpHashNode * hashNode;
  133. if (hashTable == NULL) {
  134. return;
  135. }
  136. // free hash table and nodes
  137. for (i=0; i < HASH_TABLE_SIZE; i++) {
  138. // point to first item
  139. hashNode = hashTable[i];
  140. // find end of node list
  141. while (hashNode) {
  142. // save pointer to next node
  143. nextNode = hashNode->nextEntry;
  144. // free current node
  145. SnmpUtilMemFree(hashNode);
  146. // retrieve next
  147. hashNode = nextNode;
  148. }
  149. }
  150. // release table itself
  151. SnmpUtilMemFree(hashTable);
  152. }
  153. SnmpHashNode **
  154. AllocHashTable(
  155. SnmpMibView * mibView
  156. )
  157. /*++
  158. Routine Description:
  159. Initializes view hash table.
  160. Arguments:
  161. mibView - mib view information.
  162. Return Values:
  163. Returns pointer to first entry if successful.
  164. --*/
  165. {
  166. UINT i;
  167. UINT j;
  168. UINT numItems;
  169. BOOL fInitedOk;
  170. SnmpMibEntry * mibEntry;
  171. SnmpHashNode * hashNode;
  172. SnmpHashNode ** hashTable = NULL;
  173. // validate parameter
  174. if (mibView == NULL) {
  175. return NULL;
  176. }
  177. // determine how many items in view
  178. numItems = mibView->viewScalars.len;
  179. // load the first entry in the view
  180. mibEntry = mibView->viewScalars.list;
  181. // allocate hash table using predefined size
  182. hashTable = (SnmpHashNode **)SnmpUtilMemAlloc(
  183. HASH_TABLE_SIZE * sizeof(SnmpHashNode *)
  184. );
  185. // make sure table is allocated
  186. fInitedOk = (hashTable != NULL);
  187. SNMPDBG((
  188. SNMP_LOG_VERBOSE,
  189. "SNMP: TFX: initializing hash table 0x%08lx (%d items).\n",
  190. hashTable,
  191. numItems
  192. ));
  193. // process each item in the subagent's supported view
  194. for (i = 0; (i < numItems) && fInitedOk; i++, mibEntry++) {
  195. // hash into table index
  196. j = OidToHashTableIndex(&mibEntry->mibOid);
  197. // check if table entry taken
  198. if (hashTable[j] == NULL) {
  199. // allocate new node
  200. hashNode = (SnmpHashNode *)SnmpUtilMemAlloc(
  201. sizeof(SnmpHashNode)
  202. );
  203. // save hash node
  204. hashTable[j] = hashNode;
  205. SNMPDBG((
  206. SNMP_LOG_VERBOSE,
  207. "SNMP: TFX: adding hash node 0x%08lx to empty slot %d (0x%08lx).\n",
  208. hashNode, j, mibEntry
  209. ));
  210. } else {
  211. // point to first item
  212. hashNode = hashTable[j];
  213. // find end of node list
  214. while (hashNode->nextEntry) {
  215. hashNode = hashNode->nextEntry;
  216. }
  217. // allocate new node entry
  218. hashNode->nextEntry = (SnmpHashNode *)SnmpUtilMemAlloc(
  219. sizeof(SnmpHashNode)
  220. );
  221. // re-init node to edit below
  222. hashNode = hashNode->nextEntry;
  223. SNMPDBG((
  224. SNMP_LOG_VERBOSE,
  225. "SNMP: TFX: adding hash node 0x%08lx to full slot %d (0x%08lx).\n",
  226. hashNode, j, mibEntry
  227. ));
  228. }
  229. // make sure allocation succeeded
  230. fInitedOk = (hashNode != NULL);
  231. if (fInitedOk) {
  232. // fill in node values
  233. hashNode->mibEntry = mibEntry;
  234. }
  235. }
  236. SNMPDBG((
  237. SNMP_LOG_VERBOSE,
  238. "SNMP: TFX: %s initialized hash table 0x%08lx.\n",
  239. fInitedOk ? "successfully" : "unsuccessfully",
  240. hashTable
  241. ));
  242. if (!fInitedOk) {
  243. // free view hash table
  244. FreeHashTable(hashTable);
  245. // reinitialize
  246. hashTable = NULL;
  247. }
  248. return hashTable;
  249. }
  250. VOID
  251. OidToMibEntry(
  252. AsnObjectIdentifier * hashOid,
  253. SnmpHashNode ** hashTable,
  254. SnmpMibEntry ** mibEntry
  255. )
  256. /*++
  257. Routine Description:
  258. Returns mib entry associated with given object identifier.
  259. Arguments:
  260. hashOid - oid to convert to table index.
  261. hashTable - table to look up entry.
  262. mibEntry - pointer to mib entry information.
  263. Return Values:
  264. None.
  265. --*/
  266. {
  267. UINT i;
  268. SnmpHashNode * hashNode;
  269. AsnObjectIdentifier newOid;
  270. // create index
  271. i = OidToHashTableIndex(hashOid);
  272. SNMPDBG((
  273. SNMP_LOG_VERBOSE,
  274. "SNMP: TFX: searching hash table 0x%08lx slot %d for %s.\n",
  275. hashTable, i, SnmpUtilOidToA(hashOid)
  276. ));
  277. // retrieve node
  278. hashNode = hashTable[i];
  279. // initialize
  280. *mibEntry = NULL;
  281. // search list
  282. while (hashNode) {
  283. SNMPDBG((
  284. SNMP_LOG_VERBOSE,
  285. "SNMP: TFX: searching hash node 0x%08lx (mibe=0x%08lx) - %s.\n",
  286. hashNode, hashNode->mibEntry,
  287. SnmpUtilOidToA(&hashNode->mibEntry->mibOid)
  288. ));
  289. // retrieve mib identifier
  290. newOid = hashNode->mibEntry->mibOid;
  291. // make sure that the oid matches
  292. if (!SnmpUtilOidCmp(&newOid, hashOid)) {
  293. SNMPDBG((
  294. SNMP_LOG_VERBOSE,
  295. "SNMP: TFX: returning mib entry 0x%08lx.\n",
  296. hashNode->mibEntry
  297. ));
  298. // return node data
  299. *mibEntry = hashNode->mibEntry;
  300. return;
  301. }
  302. // check next node
  303. hashNode = hashNode->nextEntry;
  304. }
  305. }
  306. int
  307. ValidateInstanceIdentifier(
  308. AsnObjectIdentifier * indexOid,
  309. SnmpMibTable * tableInfo
  310. )
  311. /*++
  312. Routine Description:
  313. Validates that oid can be successfully parsed into index entries.
  314. Arguments:
  315. indexOid - object indentifier of potential index.
  316. tableInfo - information describing conceptual table.
  317. Return Values:
  318. Returns the comparision between the length of the indexOid
  319. and the cumulated lengths of all the indices of the table tableInfo.
  320. {-1, 0, 1}
  321. --*/
  322. {
  323. UINT i = 0;
  324. UINT j = 0;
  325. int nComp;
  326. BOOL fFixed;
  327. BOOL fLimit;
  328. BOOL fIndex;
  329. SnmpMibEntry * mibEntry;
  330. SNMPDBG((
  331. SNMP_LOG_VERBOSE,
  332. "SNMP: TFX: validating index %s via table 0x%08lx.\n",
  333. SnmpUtilOidToA(indexOid), tableInfo
  334. ));
  335. // see if the table indices are specified
  336. fIndex = (tableInfo->tableIndices != NULL);
  337. // scan mib entries of table indices ensuring match of given oid
  338. for (i = 0; (i < tableInfo->numIndices) && (j < indexOid->idLength); i++) {
  339. // get mib entry from table or directly
  340. mibEntry = fIndex ? tableInfo->tableIndices[i]
  341. : &tableInfo->tableEntry[i+1]
  342. ;
  343. // determine type
  344. switch (mibEntry->mibType) {
  345. // variable length types
  346. case ASN_OBJECTIDENTIFIER:
  347. case ASN_RFC1155_OPAQUE:
  348. case ASN_OCTETSTRING:
  349. // check whether this is a fixed length variable or not
  350. fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
  351. fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
  352. // validate
  353. if (fFixed) {
  354. // increment fixed length
  355. j += mibEntry->mibMaximum;
  356. } else if (fLimit) {
  357. // check whether the length of the variable is valid
  358. if (((INT)indexOid->ids[j] >= mibEntry->mibMinimum) &&
  359. ((INT)indexOid->ids[j] <= mibEntry->mibMaximum)) {
  360. // increment given length
  361. j += (indexOid->ids[j] + 1);
  362. } else {
  363. // invalidate
  364. j = INVALID_INDEX;
  365. }
  366. } else {
  367. // increment given length
  368. j += (indexOid->ids[j] + 1);
  369. }
  370. break;
  371. // implicit fixed size
  372. case ASN_RFC1155_IPADDRESS:
  373. // increment
  374. j += 4;
  375. break;
  376. case ASN_RFC1155_COUNTER:
  377. case ASN_RFC1155_GAUGE:
  378. case ASN_RFC1155_TIMETICKS:
  379. case ASN_INTEGER:
  380. // increment
  381. j++;
  382. break;
  383. default:
  384. // invalidate
  385. j = INVALID_INDEX;
  386. break;
  387. }
  388. }
  389. if (i<tableInfo->numIndices)
  390. nComp = -1;
  391. else if (j < indexOid->idLength)
  392. nComp = 1;
  393. else if (j > indexOid->idLength)
  394. nComp = -1;
  395. else
  396. nComp = 0;
  397. SNMPDBG((
  398. SNMP_LOG_VERBOSE,
  399. "SNMP: TFX: ValidateInstanceIdentifier; OID %s %s table indices.\n",
  400. SnmpUtilOidToA(indexOid),
  401. nComp > 0 ? "over-covers" : nComp < 0 ? "shorter than" : "matches"
  402. ));
  403. return nComp;
  404. }
  405. VOID
  406. ValidateAsnAny(
  407. AsnAny * asnAny,
  408. SnmpMibEntry * mibEntry,
  409. UINT mibAction,
  410. UINT * errorStatus
  411. )
  412. /*++
  413. Routine Description:
  414. Validates asn value with given mib entry.
  415. Arguments:
  416. asnAny - value to set.
  417. mibEntry - mib information.
  418. mibAction - mib action to be taken.
  419. errorStatus - used to indicate success or failure.
  420. Return Values:
  421. None.
  422. --*/
  423. {
  424. BOOL fLimit;
  425. BOOL fFixed;
  426. INT asnLen;
  427. BOOL fOk = TRUE;
  428. SNMPDBG((
  429. SNMP_LOG_VERBOSE,
  430. "SNMP: TFX: validating value for %s request using entry 0x%08lx.\n",
  431. (mibAction == MIB_ACTION_SET) ? "write" : "read", mibEntry
  432. ));
  433. // validating gets is trivial
  434. if (mibAction != MIB_ACTION_SET) {
  435. // validate instrumentation info
  436. if ((mibEntry->mibGetBufLen == 0) ||
  437. (mibEntry->mibGetFunc == NULL) ||
  438. !(mibEntry->mibAccess & MIB_ACCESS_READ)) {
  439. // variable is not available for reading
  440. *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  441. SNMPDBG((
  442. SNMP_LOG_VERBOSE,
  443. "SNMP: TFX: entry 0x%08lx not read-enabled.\n",
  444. mibEntry
  445. ));
  446. return; // bail...
  447. }
  448. } else {
  449. // validate instrumentation info
  450. if ((mibEntry->mibSetBufLen == 0) ||
  451. (mibEntry->mibSetFunc == NULL) ||
  452. !(mibEntry->mibAccess & MIB_ACCESS_WRITE)) {
  453. // variable is not avaiLable for writing
  454. *errorStatus = SNMP_ERRORSTATUS_NOTWRITABLE;
  455. SNMPDBG((
  456. SNMP_LOG_VERBOSE,
  457. "SNMP: TFX: entry 0x%08lx not write-enabled.\n",
  458. mibEntry
  459. ));
  460. return; // bail...
  461. }
  462. if (mibEntry->mibType != asnAny->asnType)
  463. {
  464. *errorStatus = SNMP_ERRORSTATUS_BADVALUE;
  465. SNMPDBG((
  466. SNMP_LOG_VERBOSE,
  467. "SNMP: TFX: entry 0x%08lx doesn't match the asnType",
  468. mibEntry));
  469. return; // bail...
  470. }
  471. // check whether this is a fixed length variable or not
  472. fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
  473. fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
  474. // determine value type
  475. switch (asnAny->asnType) {
  476. // variable length types
  477. case ASN_OBJECTIDENTIFIER:
  478. // retrieve the objects id length
  479. asnLen = asnAny->asnValue.object.idLength;
  480. // fixed?
  481. if (fFixed) {
  482. // make sure the length is correct
  483. fOk = (asnLen == mibEntry->mibMaximum);
  484. } else if (fLimit) {
  485. // make sure the length is correct
  486. fOk = ((asnLen >= mibEntry->mibMinimum) &&
  487. (asnLen <= mibEntry->mibMaximum));
  488. }
  489. break;
  490. case ASN_RFC1155_OPAQUE:
  491. case ASN_OCTETSTRING:
  492. // retrieve the arbitrary length
  493. asnLen = asnAny->asnValue.string.length;
  494. // fixed?
  495. if (fFixed) {
  496. // make sure the length is correct
  497. fOk = (asnLen == mibEntry->mibMaximum);
  498. } else if (fLimit) {
  499. // make sure the length is correct
  500. fOk = ((asnLen >= mibEntry->mibMinimum) &&
  501. (asnLen <= mibEntry->mibMaximum));
  502. }
  503. break;
  504. case ASN_RFC1155_IPADDRESS:
  505. // make sure the length is correct
  506. fOk = (asnAny->asnValue.address.length == 4);
  507. break;
  508. case ASN_INTEGER:
  509. // limited?
  510. if (fLimit) {
  511. // make sure the value in range
  512. fOk = ((asnAny->asnValue.number >= mibEntry->mibMinimum) &&
  513. (asnAny->asnValue.number <= mibEntry->mibMaximum));
  514. }
  515. break;
  516. default:
  517. // error...
  518. fOk = FALSE;
  519. break;
  520. }
  521. }
  522. SNMPDBG((
  523. SNMP_LOG_VERBOSE,
  524. "SNMP: TFX: value is %s using entry 0x%08lx.\n",
  525. fOk ? "valid" : "invalid", mibEntry
  526. ));
  527. // report results
  528. *errorStatus = fOk
  529. ? SNMP_ERRORSTATUS_NOERROR
  530. : SNMP_ERRORSTATUS_BADVALUE
  531. ;
  532. }
  533. VOID
  534. FindMibEntry(
  535. SnmpTfxInfo * tfxInfo,
  536. RFC1157VarBind * vb,
  537. SnmpMibEntry ** mibEntry,
  538. UINT * mibAction,
  539. SnmpTableXlat ** tblXlat,
  540. UINT vlIndex,
  541. UINT * errorStatus
  542. )
  543. /*++
  544. Routine Description:
  545. Locates mib entry associated with given varbind.
  546. Arguments:
  547. tfxInfo - context info.
  548. vb - variable to locate.
  549. mibEntry - mib entry information.
  550. mibAction - mib action (may be updated).
  551. tblXlat - table translation info.
  552. vlIndex - index into view list.
  553. errorStatus - used to indicate success or failure.
  554. Return Values:
  555. None.
  556. --*/
  557. {
  558. UINT i;
  559. UINT j;
  560. UINT newIndex;
  561. UINT numItems;
  562. UINT numTables;
  563. BOOL fFoundOk;
  564. int indexComp;
  565. AsnObjectIdentifier hashOid;
  566. AsnObjectIdentifier indexOid;
  567. AsnObjectIdentifier * viewOid;
  568. SnmpMibTable * viewTables;
  569. SnmpTfxView * tfxView;
  570. SnmpMibEntry * newEntry = NULL;
  571. SnmpTableXlat * newXlat = NULL;
  572. // initialize
  573. *mibEntry = NULL;
  574. *tblXlat = NULL;
  575. // retrieve view information
  576. tfxView = &tfxInfo->tfxViews[vlIndex];
  577. // retrieve view object identifier
  578. viewOid = &tfxView->mibView->viewOid;
  579. SNMPDBG((
  580. SNMP_LOG_VERBOSE,
  581. "SNMP: TFX: FindMibEntry; comp(%s, ",
  582. SnmpUtilOidToA(&vb->name)
  583. ));
  584. SNMPDBG((
  585. SNMP_LOG_VERBOSE,
  586. "%s).\n",
  587. SnmpUtilOidToA(viewOid)
  588. ));
  589. // if the prefix exactly matchs it is root oid
  590. if (!SnmpUtilOidCmp(&vb->name, viewOid)) {
  591. SNMPDBG((SNMP_LOG_VERBOSE, "SNMP: TFX: requested oid is root.\n"));
  592. *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  593. return;
  594. }
  595. // if the prefix does not match it is not in hash table
  596. if (SnmpUtilOidNCmp(&vb->name, viewOid, viewOid->idLength)) {
  597. SNMPDBG((SNMP_LOG_TRACE, "SNMP: TFX: requested oid not in view.\n"));
  598. *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  599. return;
  600. }
  601. // construct new oid sans root prefix
  602. hashOid.ids = &vb->name.ids[viewOid->idLength];
  603. hashOid.idLength = vb->name.idLength - viewOid->idLength;
  604. // retrieve mib entry and index via hash table
  605. OidToMibEntry(&hashOid, tfxView->hashTable, &newEntry);
  606. // check if mib entry found
  607. fFoundOk = (newEntry != NULL);
  608. // try mib tables
  609. if (!fFoundOk) {
  610. SNMPDBG((
  611. SNMP_LOG_VERBOSE,
  612. "SNMP: TFX: searching mib tables for %s.\n",
  613. SnmpUtilOidToA(&hashOid)
  614. ));
  615. // retrieve mib table information
  616. numTables = tfxView->mibView->viewTables.len;
  617. viewTables = tfxView->mibView->viewTables.list;
  618. // scan mib tables for a match to the given oid
  619. for (i=0; (i < numTables) && !fFoundOk; i++, viewTables++) {
  620. // retrieve entry for table entry
  621. numItems = viewTables->numColumns;
  622. newEntry = viewTables->tableEntry;
  623. if (!SnmpUtilOidNCmp(
  624. &hashOid,
  625. &newEntry->mibOid,
  626. newEntry->mibOid.idLength)) {
  627. SNMPDBG((
  628. SNMP_LOG_VERBOSE,
  629. "SNMP: TFX: searching table 0x%08lx (%s).\n",
  630. newEntry, SnmpUtilOidToA(&newEntry->mibOid)
  631. ));
  632. // next
  633. ++newEntry;
  634. // scan mib table entries for a match
  635. for (j=0; j < numItems; j++, newEntry++) {
  636. // compare with oid of table entry
  637. if (!SnmpUtilOidNCmp(
  638. &hashOid,
  639. &newEntry->mibOid,
  640. newEntry->mibOid.idLength)) {
  641. SNMPDBG((
  642. SNMP_LOG_VERBOSE,
  643. "SNMP: TFX: validating mib entry 0x%08lx (%s).\n",
  644. newEntry, SnmpUtilOidToA(&newEntry->mibOid)
  645. ));
  646. // construct new oid sans table entry prefix
  647. indexOid.ids =
  648. &hashOid.ids[newEntry->mibOid.idLength];
  649. indexOid.idLength =
  650. hashOid.idLength - newEntry->mibOid.idLength;
  651. // verify rest of oid is valid index
  652. indexComp = ValidateInstanceIdentifier(
  653. &indexOid,
  654. viewTables
  655. );
  656. fFoundOk = (indexComp < 0 && *mibAction == MIB_ACTION_GETNEXT) ||
  657. (indexComp == 0);
  658. // is index?
  659. if (fFoundOk) {
  660. SNMPDBG((
  661. SNMP_LOG_VERBOSE,
  662. "SNMP: TFX: saving index oid %s.\n",
  663. SnmpUtilOidToA(&indexOid)
  664. ));
  665. // alloc a table traslation entry only if the object is accessible
  666. if (newEntry->mibAccess != MIB_ACCESS_NONE)
  667. {
  668. // allocate table translation structure
  669. newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
  670. sizeof(SnmpTableXlat)
  671. );
  672. // Prefix bug # 445169
  673. if (newXlat != NULL)
  674. {
  675. // copy index object identifier
  676. if (! SnmpUtilOidCpy(&newXlat->txOid, &indexOid))
  677. {
  678. // report memory allocation problem
  679. SNMPDBG((
  680. SNMP_LOG_ERROR,
  681. "SNMP: TFX: SnmpUtilOidCpy at line %d failed.\n",
  682. __LINE__));
  683. // free previous allocated memory
  684. SnmpUtilMemFree(newXlat);
  685. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  686. return; // bail...
  687. }
  688. // save table information
  689. newXlat->txInfo = viewTables;
  690. newXlat->txIndex = i;
  691. }
  692. else
  693. {
  694. // report memory allocation problem
  695. SNMPDBG((
  696. SNMP_LOG_ERROR,
  697. "SNMP: TFX: unable to allocate memory.\n"
  698. ));
  699. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  700. return; // bail...
  701. }
  702. }
  703. break; // finished...
  704. }
  705. }
  706. }
  707. }
  708. }
  709. } else {
  710. UINT newOff;
  711. SNMPDBG((
  712. SNMP_LOG_VERBOSE,
  713. "SNMP: TFX: searching mib tables for %s.\n",
  714. SnmpUtilOidToA(&hashOid)
  715. ));
  716. // retrieve mib table information
  717. numTables = tfxView->mibView->viewTables.len;
  718. viewTables = tfxView->mibView->viewTables.list;
  719. // scan mib tables for an entry in table
  720. for (i=0; i < numTables; i++, viewTables++) {
  721. // columns are positioned after entry
  722. if (newEntry > viewTables->tableEntry) {
  723. // calculate the difference between pointers
  724. newOff = (UINT)((ULONG_PTR)newEntry - (ULONG_PTR)viewTables->tableEntry);
  725. // calculate table offset
  726. newOff /= sizeof(SnmpMibEntry);
  727. // determine if entry within region
  728. if (newOff <= viewTables->numColumns &&
  729. newEntry->mibAccess != MIB_ACCESS_NONE) {
  730. // allocate table translation structure
  731. newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
  732. sizeof(SnmpTableXlat)
  733. );
  734. // Prefix bug # 445169
  735. if (newXlat != NULL)
  736. {
  737. // save table information
  738. newXlat->txInfo = viewTables;
  739. newXlat->txIndex = i;
  740. // initialize index oid
  741. newXlat->txOid.ids = NULL;
  742. newXlat->txOid.idLength = 0;
  743. SNMPDBG((
  744. SNMP_LOG_TRACE,
  745. "SNMP: TFX: mib entry is in table 0x%08lx (%s).\n",
  746. viewTables->tableEntry,
  747. SnmpUtilOidToA(&viewTables->tableEntry->mibOid)
  748. ));
  749. break; // finished...
  750. }
  751. else
  752. {
  753. // report memory allocation problem
  754. SNMPDBG((
  755. SNMP_LOG_ERROR,
  756. "SNMP: TFX: unable to allocate memory.\n"
  757. ));
  758. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  759. return; // bail...
  760. }
  761. }
  762. }
  763. }
  764. }
  765. // found entry?
  766. if (fFoundOk) {
  767. SNMPDBG((
  768. SNMP_LOG_VERBOSE,
  769. "SNMP: TFX: FindMibEntry; found %s\n",
  770. SnmpUtilOidToA(&newEntry->mibOid)
  771. ));
  772. // pass back results
  773. *mibEntry = newEntry;
  774. *tblXlat = newXlat;
  775. } else {
  776. SNMPDBG((
  777. SNMP_LOG_VERBOSE,
  778. "SNMP: TFX: unable to exactly match varbind.\n"
  779. ));
  780. // unable to locate varbind in mib table
  781. *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  782. }
  783. }
  784. VOID
  785. FindNextMibEntry(
  786. SnmpTfxInfo * tfxInfo,
  787. RFC1157VarBind * vb,
  788. SnmpMibEntry ** mibEntry,
  789. UINT * mibAction,
  790. SnmpTableXlat ** tblXlat,
  791. UINT vlIndex,
  792. UINT * errorStatus
  793. )
  794. /*++
  795. Routine Description:
  796. Locates next mib entry associated with given varbind.
  797. Arguments:
  798. tfxInfo - context info.
  799. vb - variable to locate.
  800. mibEntry - mib entry information.
  801. mibAction - mib action (may be updated).
  802. tblXlat - table translation info.
  803. vlIndex - index into view list.
  804. errorStatus - used to indicate success or failure.
  805. Return Values:
  806. None.
  807. --*/
  808. {
  809. UINT mibStatus;
  810. SnmpMibEntry * newEntry = NULL;
  811. SnmpTableXlat * newXlat = NULL;
  812. SnmpTfxView * tfxView;
  813. // table?
  814. if (*tblXlat) {
  815. SNMPDBG((SNMP_LOG_VERBOSE, "SNMP: TFX: querying table.\n"));
  816. return; // simply query table...
  817. }
  818. // retrieve view information
  819. tfxView = &tfxInfo->tfxViews[vlIndex];
  820. // retrieve entry
  821. newEntry = *mibEntry;
  822. // initialize
  823. *mibEntry = NULL;
  824. *tblXlat = NULL;
  825. // continuing?
  826. if (newEntry) {
  827. // next
  828. ++newEntry;
  829. SNMPDBG((
  830. SNMP_LOG_TRACE,
  831. "SNMP: TFX: searching mib at next entry 0x%08lx (%s).\n",
  832. newEntry,
  833. SnmpUtilOidToA(&newEntry->mibOid)
  834. ));
  835. } else {
  836. // retrieve first mib entry in supported view
  837. newEntry = tfxView->mibView->viewScalars.list;
  838. SNMPDBG((
  839. SNMP_LOG_TRACE,
  840. "SNMP: TFX: searching mib at first entry 0x%08lx.\n",
  841. newEntry
  842. ));
  843. }
  844. // initialize status to start search
  845. mibStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  846. // scan
  847. for (;; newEntry++) {
  848. SNMPDBG((
  849. SNMP_LOG_VERBOSE,
  850. "SNMP: TFX: FindNextMibEntry; scanning view %s ",
  851. SnmpUtilOidToA(&tfxView->mibView->viewOid)
  852. ));
  853. SNMPDBG((
  854. SNMP_LOG_VERBOSE,
  855. " scalar %s.\n",
  856. SnmpUtilOidToA(&newEntry->mibOid)
  857. ));
  858. // if last entry then we stop looking
  859. if (newEntry->mibType == ASN_PRIVATE_EOM) {
  860. SNMPDBG((SNMP_LOG_TRACE, "SNMP: TFX: encountered end of mib.\n"));
  861. *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  862. return; // bail...
  863. }
  864. // skip over place holder mib entries
  865. if (newEntry->mibType != ASN_PRIVATE_NODE) {
  866. // validate asn value against info in mib entry
  867. ValidateAsnAny(&vb->value, newEntry, *mibAction, &mibStatus);
  868. // bail if we found a valid entry...
  869. if (mibStatus == SNMP_ERRORSTATUS_NOERROR) {
  870. break;
  871. }
  872. }
  873. }
  874. // retrieved an entry but is it in a table?
  875. if (mibStatus == SNMP_ERRORSTATUS_NOERROR) {
  876. UINT i;
  877. UINT newOff;
  878. UINT numTables;
  879. SnmpMibTable * viewTables;
  880. SNMPDBG((
  881. SNMP_LOG_TRACE,
  882. "SNMP: TFX: mib entry 0x%08lx found (%s).\n",
  883. newEntry, SnmpUtilOidToA(&newEntry->mibOid)
  884. ));
  885. // retrieve table information from view
  886. numTables = tfxView->mibView->viewTables.len;
  887. viewTables = tfxView->mibView->viewTables.list;
  888. // scan mib tables for an entry in table
  889. for (i=0; i < numTables; i++, viewTables++) {
  890. // columns are positioned after entry
  891. if (newEntry > viewTables->tableEntry) {
  892. // calculate the difference between pointers
  893. newOff = (UINT)((ULONG_PTR)newEntry - (ULONG_PTR)viewTables->tableEntry);
  894. // calculate table offset
  895. newOff /= sizeof(SnmpMibEntry);
  896. // determine if entry within region
  897. if (newOff <= viewTables->numColumns) {
  898. // allocate table translation structure
  899. newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
  900. sizeof(SnmpTableXlat)
  901. );
  902. // Prefix bug # 445169
  903. if (newXlat != NULL)
  904. {
  905. // save table information
  906. newXlat->txInfo = viewTables;
  907. newXlat->txIndex = i;
  908. // initialize index oid
  909. newXlat->txOid.ids = NULL;
  910. newXlat->txOid.idLength = 0;
  911. SNMPDBG((
  912. SNMP_LOG_TRACE,
  913. "SNMP: TFX: mib entry is in table 0x%08lx (%s).\n",
  914. viewTables->tableEntry,
  915. SnmpUtilOidToA(&viewTables->tableEntry->mibOid)
  916. ));
  917. break; // finished...
  918. }
  919. else
  920. {
  921. // report memory allocation problem
  922. SNMPDBG((
  923. SNMP_LOG_ERROR,
  924. "SNMP: TFX: unable to allocate memory.\n"
  925. ));
  926. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  927. return; // bail...
  928. }
  929. }
  930. }
  931. }
  932. // pass back results
  933. *mibEntry = newEntry;
  934. *tblXlat = newXlat;
  935. // update mib action of scalar getnext
  936. if (!newXlat && (*mibAction == MIB_ACTION_GETNEXT)) {
  937. *mibAction = MIB_ACTION_GET;
  938. SNMPDBG((
  939. SNMP_LOG_TRACE,
  940. "SNMP: TFX: altered mib action to MIB_ACTION_GET.\n"
  941. ));
  942. }
  943. }
  944. // pass back status
  945. *errorStatus = mibStatus;
  946. }
  947. VOID
  948. FindAnyMibEntry(
  949. SnmpTfxInfo * tfxInfo,
  950. RFC1157VarBind * vb,
  951. SnmpMibEntry ** mibEntry,
  952. UINT * mibAction,
  953. SnmpTableXlat ** tblXlat,
  954. UINT vlIndex,
  955. UINT * errorStatus
  956. )
  957. /*++
  958. Routine Description:
  959. Locates any mib entry associated with given varbind.
  960. Arguments:
  961. tfxInfo - context info.
  962. vb - variable to locate.
  963. mibEntry - mib entry information.
  964. mibAction - mib action (may be updated).
  965. tblXlat - table translation info.
  966. vlIndex - index into view list.
  967. errorStatus - used to indicate success or failure.
  968. Return Values:
  969. None.
  970. --*/
  971. {
  972. BOOL fExact;
  973. BOOL fBefore;
  974. SnmpTfxView * tfxView;
  975. // retrieve view information
  976. tfxView = &tfxInfo->tfxViews[vlIndex];
  977. SNMPDBG((
  978. SNMP_LOG_VERBOSE,
  979. "SNMP: TFX: FindAnyMibEntry; comp(%s, ",
  980. SnmpUtilOidToA(&vb->name)
  981. ));
  982. SNMPDBG((
  983. SNMP_LOG_VERBOSE,
  984. "%s[, %d]).\n",
  985. SnmpUtilOidToA(&tfxView->mibView->viewOid),
  986. tfxView->mibView->viewOid.idLength
  987. ));
  988. // look for oid before view
  989. fBefore = (0 > SnmpUtilOidNCmp(
  990. &vb->name,
  991. &tfxView->mibView->viewOid,
  992. tfxView->mibView->viewOid.idLength
  993. ));
  994. // look for exact match
  995. fExact = !fBefore && !SnmpUtilOidCmp(
  996. &vb->name,
  997. &tfxView->mibView->viewOid
  998. );
  999. SNMPDBG((
  1000. SNMP_LOG_VERBOSE,
  1001. "SNMP: TFX: fBefore=%d fExact=%d\n",
  1002. fBefore,
  1003. fExact
  1004. ));
  1005. // check for random oid...
  1006. if (!fBefore && !fExact) {
  1007. AsnObjectIdentifier relOid;
  1008. AsnObjectIdentifier * viewOid;
  1009. SnmpMibEntry * newEntry = NULL;
  1010. // point to the first item in the list
  1011. newEntry = tfxView->mibView->viewScalars.list;
  1012. SNMPDBG((
  1013. SNMP_LOG_TRACE,
  1014. "SNMP: TFX: linear search from first entry 0x%08lx.\n",
  1015. newEntry
  1016. ));
  1017. // retrieve the view object identifier
  1018. viewOid = &tfxView->mibView->viewOid;
  1019. // construct new oid sans root prefix
  1020. relOid.ids = &vb->name.ids[viewOid->idLength];
  1021. relOid.idLength = vb->name.idLength - viewOid->idLength;
  1022. // scan mib entries
  1023. while ((newEntry->mibType != ASN_PRIVATE_EOM) &&
  1024. (SnmpUtilOidCmp(&relOid, &newEntry->mibOid) > 0)) {
  1025. SNMPDBG((
  1026. SNMP_LOG_VERBOSE,
  1027. "SNMP: TFX: skipping %s.\n",
  1028. SnmpUtilOidToA(&newEntry->mibOid)
  1029. ));
  1030. // next
  1031. newEntry++;
  1032. }
  1033. // if last entry then we stop looking
  1034. if (newEntry->mibType == ASN_PRIVATE_EOM) {
  1035. SNMPDBG((
  1036. SNMP_LOG_TRACE,
  1037. "SNMP: TFX: encountered end of mib.\n"
  1038. ));
  1039. *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  1040. return; // bail...
  1041. }
  1042. // backup to find next
  1043. *mibEntry = --newEntry;
  1044. *tblXlat = NULL;
  1045. // find next
  1046. FindNextMibEntry(
  1047. tfxInfo,
  1048. vb,
  1049. mibEntry,
  1050. mibAction,
  1051. tblXlat,
  1052. vlIndex,
  1053. errorStatus
  1054. );
  1055. } else {
  1056. // initialize
  1057. *mibEntry = NULL;
  1058. *tblXlat = NULL;
  1059. SNMPDBG((
  1060. SNMP_LOG_TRACE,
  1061. "SNMP: TFX: searching for first entry.\n"
  1062. ));
  1063. // find next
  1064. FindNextMibEntry(
  1065. tfxInfo,
  1066. vb,
  1067. mibEntry,
  1068. mibAction,
  1069. tblXlat,
  1070. vlIndex,
  1071. errorStatus
  1072. );
  1073. SNMPDBG((
  1074. SNMP_LOG_VERBOSE,
  1075. "SNMP: TFX: FindAnyMibEntry; error %d on %s(.",
  1076. *errorStatus,
  1077. SnmpUtilOidToA(&tfxInfo->tfxViews[vlIndex].mibView->viewOid)
  1078. ));
  1079. SNMPDBG((
  1080. SNMP_LOG_VERBOSE,
  1081. "%s).\n",
  1082. SnmpUtilOidToA(&(*mibEntry)->mibOid)
  1083. ));
  1084. }
  1085. }
  1086. VOID
  1087. VarBindToMibEntry(
  1088. SnmpTfxInfo * tfxInfo,
  1089. RFC1157VarBind * vb,
  1090. SnmpMibEntry ** mibEntry,
  1091. UINT * mibAction,
  1092. SnmpTableXlat ** tblXlat,
  1093. UINT vlIndex,
  1094. UINT * errorStatus
  1095. )
  1096. /*++
  1097. Routine Description:
  1098. Locates mib entry associated with given varbind.
  1099. Arguments:
  1100. tfxInfo - context information.
  1101. vb - variable to locate.
  1102. mibEntry - mib entry information.
  1103. mibAction - mib action (may be updated).
  1104. tblXlat - table translation info.
  1105. vlIndex - index into view list.
  1106. errorStatus - used to indicate success or failure.
  1107. Return Values:
  1108. None.
  1109. --*/
  1110. {
  1111. BOOL fAnyOk;
  1112. BOOL fFoundOk;
  1113. BOOL fErrorOk;
  1114. // determine whether we need exact match
  1115. fAnyOk = (*mibAction == MIB_ACTION_GETNEXT);
  1116. // find match
  1117. FindMibEntry(
  1118. tfxInfo,
  1119. vb,
  1120. mibEntry,
  1121. mibAction,
  1122. tblXlat,
  1123. vlIndex,
  1124. errorStatus
  1125. );
  1126. SNMPDBG((
  1127. SNMP_LOG_VERBOSE,
  1128. "SNMP: TFX: VarBindToMibEntry; errorStatus=%d.\n",
  1129. *errorStatus
  1130. ));
  1131. // get next?
  1132. if (fAnyOk) {
  1133. // search again
  1134. if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
  1135. // find next entry
  1136. FindNextMibEntry(
  1137. tfxInfo,
  1138. vb,
  1139. mibEntry,
  1140. mibAction,
  1141. tblXlat,
  1142. vlIndex,
  1143. errorStatus
  1144. );
  1145. } else if (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME) {
  1146. // find any entry
  1147. FindAnyMibEntry(
  1148. tfxInfo,
  1149. vb,
  1150. mibEntry,
  1151. mibAction,
  1152. tblXlat,
  1153. vlIndex,
  1154. errorStatus
  1155. );
  1156. }
  1157. } else if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
  1158. // validate asn value against mib entry information
  1159. ValidateAsnAny(&vb->value, *mibEntry, *mibAction, errorStatus);
  1160. // make sure valid before passing back entry
  1161. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
  1162. // table entry?
  1163. if (*tblXlat) {
  1164. SNMPDBG((
  1165. SNMP_LOG_VERBOSE,
  1166. "SNMP: TFX: freeing index info (%s).\n",
  1167. SnmpUtilOidToA(&(*tblXlat)->txOid)
  1168. ));
  1169. // free index oid
  1170. SnmpUtilOidFree(&(*tblXlat)->txOid);
  1171. // free table info
  1172. SnmpUtilMemFree(*tblXlat);
  1173. }
  1174. // nullify results
  1175. *mibEntry = NULL;
  1176. *tblXlat = NULL;
  1177. }
  1178. }
  1179. }
  1180. BOOL
  1181. CheckUpdateIndex(
  1182. AsnObjectIdentifier *indexOid,
  1183. UINT nStartFrom,
  1184. UINT nExpecting
  1185. )
  1186. /*++
  1187. Routine Description:
  1188. Checks if an index OID contains all the components expected.
  1189. If not, the index is updated to point before the very first
  1190. OID requested.
  1191. Arguments:
  1192. indexOid - pointer to the index to be checked.
  1193. nStartFrom - the point from where the index is checked.
  1194. nExpecting - the index should have at least expectTo components from startFrom.
  1195. Return value:
  1196. TRUE if index was valid or has been updated successfully.
  1197. FALSE otherwise (index was shorter then expected and all filled with 0s).
  1198. --*/
  1199. {
  1200. int i;
  1201. SNMPDBG((
  1202. SNMP_LOG_VERBOSE,
  1203. "SNMP: TFX: CheckUpdateIndex; checking %s.\n",
  1204. SnmpUtilOidToA(indexOid)
  1205. ));
  1206. if (indexOid->idLength >= nStartFrom + nExpecting)
  1207. {
  1208. SNMPDBG((
  1209. SNMP_LOG_VERBOSE,
  1210. "SNMP: TFX: CheckUpdateIndex; valid, unchanged.\n"
  1211. ));
  1212. return TRUE;
  1213. }
  1214. for (i = indexOid->idLength-1; i >= (int)nStartFrom; i--)
  1215. {
  1216. if (indexOid->ids[i] > 0)
  1217. {
  1218. indexOid->ids[i]--;
  1219. indexOid->idLength = i+1;
  1220. SNMPDBG((
  1221. SNMP_LOG_VERBOSE,
  1222. "SNMP: TFX: CheckUpdateIndex; valid, changed to %s.\n",
  1223. SnmpUtilOidToA(indexOid)
  1224. ));
  1225. return TRUE;
  1226. }
  1227. }
  1228. SNMPDBG((
  1229. SNMP_LOG_VERBOSE,
  1230. "SNMP: TFX: CheckUpdateIndex; invalid, to be removed.\n"
  1231. ));
  1232. return FALSE;
  1233. }
  1234. VOID
  1235. ParseInstanceIdentifier(
  1236. SnmpTableXlat * tblXlat,
  1237. AsnAny * objArray,
  1238. UINT mibAction,
  1239. UINT * errorStatus
  1240. )
  1241. /*++
  1242. Routine Description:
  1243. Converts table index oid into object array.
  1244. Arguments:
  1245. tblXlat - table translation information.
  1246. objArray - instrumentation object array.
  1247. mibAction - action requested of subagent.
  1248. Return Values:
  1249. None.
  1250. --*/
  1251. {
  1252. UINT i;
  1253. UINT j;
  1254. UINT k;
  1255. UINT l;
  1256. UINT m;
  1257. BOOL fFixed;
  1258. BOOL fLimit;
  1259. BOOL fIndex;
  1260. BOOL fEmpty;
  1261. BOOL fExceed;
  1262. UINT numItems;
  1263. SnmpMibEntry * mibEntry;
  1264. AsnObjectIdentifier * indexOid;
  1265. LPDWORD lpIpAddress;
  1266. *errorStatus = SNMP_ERRORSTATUS_NOERROR; // init return status
  1267. // retrieve index oid
  1268. indexOid = &tblXlat->txOid;
  1269. // is this valid oid
  1270. fEmpty = (indexOid->idLength == 0);
  1271. SNMPDBG((
  1272. SNMP_LOG_TRACE,
  1273. "SNMP: TFX: converting index %s to obj array via table 0x%08lx.\n",
  1274. fEmpty ? "<tbd>" : SnmpUtilOidToA(indexOid), tblXlat->txInfo
  1275. ));
  1276. // retrieve root entry and entry count
  1277. numItems = tblXlat->txInfo->numIndices;
  1278. // see if the table indices are specified
  1279. fIndex = (tblXlat->txInfo->tableIndices != NULL);
  1280. fExceed = FALSE;
  1281. // scan mib entries of table indices
  1282. for (i=0, j=0; (i < numItems) && (j < indexOid->idLength); i++) {
  1283. // get mib entry from table or directly
  1284. mibEntry = fIndex ? tblXlat->txInfo->tableIndices[i]
  1285. : &tblXlat->txInfo->tableEntry[i+1]
  1286. ;
  1287. // retrieve array index
  1288. k = (mibAction == MIB_ACTION_SET)
  1289. ? (UINT)(CHAR)mibEntry->mibSetBufOff
  1290. : (UINT)(CHAR)mibEntry->mibGetBufOff
  1291. ;
  1292. // determine type
  1293. switch (mibEntry->mibType) {
  1294. // variable length types
  1295. case ASN_OBJECTIDENTIFIER:
  1296. // check whether this is a fixed length variable or not
  1297. fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
  1298. fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
  1299. // validate
  1300. if (fFixed) {
  1301. // fixed length; indexOid should have at least l components more
  1302. l = mibEntry->mibMaximum;
  1303. if (!CheckUpdateIndex(indexOid, j, l))
  1304. {
  1305. // out from switch and for
  1306. j+=l;
  1307. break;
  1308. }
  1309. } else {
  1310. // variable length
  1311. l = indexOid->ids[j];
  1312. if (!CheckUpdateIndex(indexOid, j, l+1))
  1313. {
  1314. // out from switch and for
  1315. j+=l+1;
  1316. break;
  1317. }
  1318. // BUG# 457746
  1319. // the length of OID might have been changed by
  1320. // CheckUpdateIndex
  1321. l = indexOid->ids[j]; // update the length if necessary
  1322. j++;
  1323. }
  1324. // copy the type of asn variable
  1325. objArray[k].asnType = mibEntry->mibType;
  1326. // allocate object using length above
  1327. objArray[k].asnValue.object.idLength = l;
  1328. objArray[k].asnValue.object.ids = SnmpUtilMemAlloc(
  1329. objArray[k].asnValue.object.idLength * sizeof(UINT)
  1330. );
  1331. if (objArray[k].asnValue.object.ids == NULL)
  1332. {
  1333. // report memory allocation problem
  1334. SNMPDBG((
  1335. SNMP_LOG_ERROR,
  1336. "SNMP: TFX: unable to allocate memory.\n"
  1337. ));
  1338. objArray[k].asnValue.object.idLength = 0;
  1339. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1340. return; // bail...
  1341. }
  1342. // transfer data
  1343. for (m=0; m < l; m++, j++) {
  1344. // transfer oid element to buffer
  1345. if (!fExceed && j < indexOid->idLength)
  1346. {
  1347. objArray[k].asnValue.object.ids[m] = indexOid->ids[j];
  1348. }
  1349. else
  1350. {
  1351. if (!fExceed)
  1352. fExceed = TRUE;
  1353. // this certainly is the last index from the request
  1354. }
  1355. if (fExceed)
  1356. {
  1357. objArray[k].asnValue.object.ids[m] = (UINT)(-1);
  1358. }
  1359. }
  1360. break;
  1361. case ASN_RFC1155_OPAQUE:
  1362. case ASN_OCTETSTRING:
  1363. // check whether this is a fixed length variable or not
  1364. fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
  1365. fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
  1366. // validate
  1367. if (fFixed) {
  1368. // fixed length
  1369. l = mibEntry->mibMaximum;
  1370. if (!CheckUpdateIndex(indexOid, j, l))
  1371. {
  1372. // out from switch and for
  1373. j+=l;
  1374. break;
  1375. }
  1376. } else {
  1377. // variable length
  1378. l = indexOid->ids[j];
  1379. if (!CheckUpdateIndex(indexOid, j, l+1))
  1380. {
  1381. j+=l+1;
  1382. break;
  1383. }
  1384. // BUG# 457746
  1385. // the length of octet string might have been changed by
  1386. // CheckUpdateIndex
  1387. l = indexOid->ids[j]; // update the length if necessary
  1388. j++;
  1389. }
  1390. // copy the type of asn variable
  1391. objArray[k].asnType = mibEntry->mibType;
  1392. // allocate object
  1393. objArray[k].asnValue.string.length = l;
  1394. objArray[k].asnValue.string.dynamic = TRUE;
  1395. objArray[k].asnValue.string.stream = SnmpUtilMemAlloc(
  1396. objArray[k].asnValue.string.length * sizeof(CHAR)
  1397. );
  1398. if (objArray[k].asnValue.string.stream == NULL)
  1399. {
  1400. // report memory allocation problem
  1401. SNMPDBG((
  1402. SNMP_LOG_ERROR,
  1403. "SNMP: TFX: unable to allocate memory.\n"
  1404. ));
  1405. objArray[k].asnValue.string.length = 0;
  1406. objArray[k].asnValue.string.dynamic = FALSE;
  1407. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1408. return; // bail...
  1409. }
  1410. // transfer data
  1411. for (m=0; m < l; m++, j++) {
  1412. // convert oid element to character
  1413. if (j < indexOid->idLength)
  1414. {
  1415. if (!fExceed && indexOid->ids[j] <= (UCHAR)(-1))
  1416. objArray[k].asnValue.string.stream[m] = (BYTE)(indexOid->ids[j]);
  1417. else
  1418. fExceed=TRUE;
  1419. }
  1420. else
  1421. {
  1422. if (!fExceed)
  1423. fExceed = TRUE;
  1424. // this certainly is the last index from the request
  1425. }
  1426. if (fExceed)
  1427. {
  1428. objArray[k].asnValue.string.stream[m] = (UCHAR)(-1);
  1429. }
  1430. }
  1431. break;
  1432. // implicit fixed size
  1433. case ASN_RFC1155_IPADDRESS:
  1434. if (!CheckUpdateIndex(indexOid, j, 4))
  1435. {
  1436. // out from switch and for
  1437. j+=4;
  1438. break;
  1439. }
  1440. // copy the type of asn variable
  1441. objArray[k].asnType = mibEntry->mibType;
  1442. // allocate object
  1443. objArray[k].asnValue.string.length = 4;
  1444. objArray[k].asnValue.string.dynamic = TRUE;
  1445. objArray[k].asnValue.string.stream = SnmpUtilMemAlloc(
  1446. objArray[k].asnValue.string.length * sizeof(CHAR)
  1447. );
  1448. if (objArray[k].asnValue.string.stream == NULL)
  1449. {
  1450. // report memory allocation problem
  1451. SNMPDBG((
  1452. SNMP_LOG_ERROR,
  1453. "SNMP: TFX: unable to allocate memory.\n"
  1454. ));
  1455. objArray[k].asnValue.string.length = 0;
  1456. objArray[k].asnValue.string.dynamic = FALSE;
  1457. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1458. return; // bail...
  1459. }
  1460. // cast to dword in order to manipulate ip address
  1461. lpIpAddress = (LPDWORD)objArray[k].asnValue.string.stream;
  1462. // transfer data into buffer
  1463. for (m=0; m<4; m++, j++)
  1464. {
  1465. *lpIpAddress <<= 8;
  1466. if (!fExceed && j < indexOid->idLength)
  1467. {
  1468. if (indexOid->ids[j] <= (UCHAR)(-1))
  1469. *lpIpAddress += indexOid->ids[j];
  1470. else
  1471. fExceed = TRUE;
  1472. }
  1473. else
  1474. {
  1475. if (!fExceed)
  1476. fExceed = TRUE;
  1477. // this certainly is the last index from the request
  1478. }
  1479. if (fExceed)
  1480. {
  1481. *lpIpAddress += (UCHAR)(-1);
  1482. }
  1483. }
  1484. // ensure network byte order
  1485. *lpIpAddress = htonl(*lpIpAddress);
  1486. break;
  1487. case ASN_RFC1155_COUNTER:
  1488. case ASN_RFC1155_GAUGE:
  1489. case ASN_RFC1155_TIMETICKS:
  1490. case ASN_INTEGER:
  1491. // copy the type of asn variable
  1492. objArray[k].asnType = mibEntry->mibType;
  1493. // transfer value as integer
  1494. objArray[k].asnValue.number = fExceed ? (UINT)(-1) : indexOid->ids[j];
  1495. j++;
  1496. break;
  1497. default:
  1498. // invalidate
  1499. j = INVALID_INDEX;
  1500. break;
  1501. }
  1502. }
  1503. }
  1504. BOOL
  1505. IsTableIndex(
  1506. SnmpMibEntry * mibEntry,
  1507. SnmpTableXlat * tblXlat
  1508. )
  1509. {
  1510. UINT newOff;
  1511. BOOL fFoundOk = FALSE;
  1512. BOOL fIndex;
  1513. SNMPDBG((
  1514. SNMP_LOG_VERBOSE,
  1515. "SNMP: TFX: comparing mibEntry 0x%08lx to table 0x%08lx.\n",
  1516. mibEntry,
  1517. tblXlat->txInfo
  1518. ));
  1519. // see if the table indices are specified
  1520. fIndex = (tblXlat->txInfo->tableIndices != NULL);
  1521. #if DBG
  1522. newOff = 0;
  1523. #endif
  1524. if (fIndex) {
  1525. // rummage through index list looking for match
  1526. for (newOff = 0; (newOff < tblXlat->txInfo->numIndices) && !fFoundOk; newOff++ ) {
  1527. // compare mib entry with the next specified index
  1528. fFoundOk = (mibEntry == tblXlat->txInfo->tableIndices[newOff]);
  1529. }
  1530. } else {
  1531. // make sure pointer greater than table entry
  1532. if (mibEntry > tblXlat->txInfo->tableEntry) {
  1533. // calculate the difference between pointers
  1534. newOff = (UINT)((ULONG_PTR)mibEntry - (ULONG_PTR)tblXlat->txInfo->tableEntry);
  1535. // calculate table offset
  1536. newOff /= sizeof(SnmpMibEntry);
  1537. // determine whether entry within region
  1538. fFoundOk = (newOff <= tblXlat->txInfo->numIndices);
  1539. }
  1540. }
  1541. SNMPDBG((
  1542. SNMP_LOG_VERBOSE,
  1543. "SNMP: TFX: mibEntry %s a component of the table's index (off=%d, len=%d).\n",
  1544. fFoundOk ? "is" : "is not",
  1545. newOff,
  1546. tblXlat->txInfo->numIndices
  1547. ));
  1548. return fFoundOk;
  1549. }
  1550. VOID
  1551. MibEntryToQueryList(
  1552. SnmpMibEntry * mibEntry,
  1553. UINT mibAction,
  1554. SnmpExtQueryList * ql,
  1555. SnmpTableXlat * tblXlat,
  1556. UINT vlIndex,
  1557. RFC1157VarBindList * vbl,
  1558. UINT vb,
  1559. UINT * errorStatus
  1560. )
  1561. /*++
  1562. Routine Description:
  1563. Converts mib entry information into subagent query.
  1564. Arguments:
  1565. mibEntry - mib information.
  1566. mibAction - action to perform.
  1567. ql - list of subagent queries.
  1568. tableXlat - table translation info.
  1569. vlIndex - index into view list.
  1570. vbl - original varbind list.
  1571. vb - original varbind.
  1572. errorStatus - used to indicate success or failure.
  1573. Return Values:
  1574. None.
  1575. --*/
  1576. {
  1577. UINT i;
  1578. UINT j;
  1579. UINT viewType;
  1580. FARPROC extFunc;
  1581. AsnAny * objArray;
  1582. SnmpExtQuery * extQuery;
  1583. SnmpExtQuery * tmpExtQuery = NULL; // prefix Bug 445172
  1584. SnmpVarBindXlat * tmpVblXlat = NULL; // prefix Bug 445172
  1585. BOOL fFoundOk = FALSE;
  1586. // determine instrumentation callback
  1587. extFunc = (mibAction == MIB_ACTION_SET)
  1588. ? (FARPROC)mibEntry->mibSetFunc
  1589. : (FARPROC)mibEntry->mibGetFunc
  1590. ;
  1591. // process existing queries
  1592. for (i=0; (i < ql->len) && !fFoundOk; i++) {
  1593. // retrieve query ptr
  1594. extQuery = &ql->query[i];
  1595. // determine if a similar query exists
  1596. fFoundOk = ((extQuery->extFunc == extFunc) &&
  1597. (extQuery->mibAction == mibAction));
  1598. // compare table indices (if any)
  1599. if (fFoundOk && extQuery->tblXlat) {
  1600. // make sure
  1601. if (tblXlat) {
  1602. // compare index oids...
  1603. fFoundOk = !SnmpUtilOidCmp(
  1604. &extQuery->tblXlat->txOid,
  1605. &tblXlat->txOid
  1606. );
  1607. } else {
  1608. // hmmm...
  1609. fFoundOk = FALSE;
  1610. }
  1611. }
  1612. }
  1613. // append entry
  1614. if (!fFoundOk) {
  1615. ql->len++; // add new query to end of list
  1616. tmpExtQuery = (SnmpExtQuery *)SnmpUtilMemReAlloc(
  1617. ql->query,
  1618. ql->len * sizeof(SnmpExtQuery)
  1619. );
  1620. // Prefix bug 445172
  1621. // check memory re-allocation
  1622. if (tmpExtQuery == NULL)
  1623. {
  1624. if (tblXlat)
  1625. {
  1626. // free table oid
  1627. SnmpUtilOidFree(&tblXlat->txOid);
  1628. // free table info
  1629. SnmpUtilMemFree(tblXlat);
  1630. }
  1631. ql->len--; // rollback
  1632. // report memory allocation problem
  1633. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1634. return; // bail...
  1635. }
  1636. ql->query = tmpExtQuery;
  1637. // retrieve new query pointer
  1638. extQuery = &ql->query[ql->len-1];
  1639. // save common information
  1640. extQuery->mibAction = mibAction;
  1641. extQuery->viewType = MIB_VIEW_NORMAL;
  1642. extQuery->extFunc = extFunc;
  1643. // initialize list
  1644. extQuery->vblNum = 0;
  1645. extQuery->vblXlat = NULL;
  1646. extQuery->tblXlat = NULL;
  1647. // size the instrumentation buffer
  1648. extQuery->extData.len = (mibAction == MIB_ACTION_SET)
  1649. ? mibEntry->mibSetBufLen
  1650. : mibEntry->mibGetBufLen
  1651. ;
  1652. // allocate the instrumentation buffer
  1653. extQuery->extData.data = SnmpUtilMemAlloc(
  1654. extQuery->extData.len
  1655. );
  1656. // check memory allocation
  1657. if (extQuery->extData.data) {
  1658. // table?
  1659. if (tblXlat) {
  1660. // retrieve object array pointer
  1661. objArray = (AsnAny *)(extQuery->extData.data);
  1662. // Prefix 118006
  1663. // initialize asn array
  1664. ParseInstanceIdentifier(tblXlat, objArray, mibAction, errorStatus);
  1665. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
  1666. {
  1667. // logging...
  1668. SNMPDBG((
  1669. SNMP_LOG_TRACE,
  1670. "SNMP: TFX: unable to ParseInstanceIdentifier with table info 0x%08lx.\n",
  1671. tblXlat
  1672. ));
  1673. SnmpUtilMemFree(extQuery->extData.data);
  1674. extQuery->extData.data = NULL; // null pointer to avoid double free or deref.
  1675. extQuery->extData.len = 0;
  1676. // free table oid
  1677. SnmpUtilOidFree(&tblXlat->txOid);
  1678. // free table info
  1679. SnmpUtilMemFree(tblXlat);
  1680. ql->len--; // rollback
  1681. return; // bail
  1682. }
  1683. // save table info
  1684. extQuery->tblXlat = tblXlat;
  1685. }
  1686. } else {
  1687. // rollback
  1688. extQuery->extData.len = 0;
  1689. ql->len--;
  1690. if (tblXlat)
  1691. {
  1692. // free table oid
  1693. SnmpUtilOidFree(&tblXlat->txOid);
  1694. // free table info
  1695. SnmpUtilMemFree(tblXlat);
  1696. }
  1697. // report memory allocation problem
  1698. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1699. return; // bail...
  1700. }
  1701. } else if (tblXlat != NULL) {
  1702. SNMPDBG((
  1703. SNMP_LOG_TRACE,
  1704. "SNMP: TFX: releasing duplicate table info 0x%08lx.\n",
  1705. tblXlat
  1706. ));
  1707. // free table oid
  1708. SnmpUtilOidFree(&tblXlat->txOid);
  1709. // free table info
  1710. SnmpUtilMemFree(tblXlat);
  1711. }
  1712. SNMPDBG((
  1713. SNMP_LOG_TRACE,
  1714. "SNMP: TFX: %s query 0x%08lx.\n",
  1715. fFoundOk ? "editing" : "adding",
  1716. extQuery
  1717. ));
  1718. // copy to index
  1719. i = extQuery->vblNum;
  1720. // allocate entry
  1721. extQuery->vblNum++;
  1722. tmpVblXlat = (SnmpVarBindXlat *)SnmpUtilMemReAlloc(
  1723. extQuery->vblXlat,
  1724. extQuery->vblNum * sizeof(SnmpVarBindXlat)
  1725. );
  1726. if (tmpVblXlat == NULL)
  1727. {
  1728. // report memory allocation problem
  1729. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1730. extQuery->vblNum--; // rollback
  1731. return; // bail...
  1732. }
  1733. extQuery->vblXlat = tmpVblXlat;
  1734. // copy common xlate information
  1735. extQuery->vblXlat[i].vblIndex = vb;
  1736. extQuery->vblXlat[i].vlIndex = vlIndex;
  1737. extQuery->vblXlat[i].extQuery = NULL;
  1738. // save translation info
  1739. extQuery->vblXlat[i].mibEntry = mibEntry;
  1740. // determine offset used
  1741. i = (mibAction == MIB_ACTION_SET)
  1742. ? (UINT)(CHAR)mibEntry->mibSetBufOff
  1743. : (UINT)(CHAR)mibEntry->mibGetBufOff
  1744. ;
  1745. // retrieve object array pointer
  1746. objArray = (AsnAny *)(extQuery->extData.data);
  1747. // fill in only asn type if get
  1748. if (mibAction != MIB_ACTION_SET) {
  1749. // ignore table indices
  1750. if (extQuery->tblXlat &&
  1751. IsTableIndex(mibEntry,extQuery->tblXlat)) {
  1752. SNMPDBG((
  1753. SNMP_LOG_VERBOSE,
  1754. "SNMP: TFX: requesting index value.\n"
  1755. ));
  1756. } else {
  1757. // initialize asn type to match entry
  1758. objArray[i].asnType = mibEntry->mibType;
  1759. }
  1760. } else {
  1761. // copy user-supplied value into buffer
  1762. if (! SnmpUtilAsnAnyCpy(&objArray[i], &vbl->list[vb].value) )
  1763. {
  1764. SNMPDBG((
  1765. SNMP_LOG_ERROR,
  1766. "SNMP: TFX: MibEntryToQueryList; SnmpUtilAsnAnyCpy failed.\n"
  1767. ));
  1768. // report memory allocation problem
  1769. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1770. extQuery->vblNum--; // invalidate this SnmpVarBindXlat
  1771. return; // bail...
  1772. }
  1773. }
  1774. }
  1775. VOID
  1776. VarBindToQueryList(
  1777. SnmpTfxInfo * tfxInfo,
  1778. RFC1157VarBindList * vbl,
  1779. SnmpExtQueryList * ql,
  1780. UINT vb,
  1781. UINT * errorStatus,
  1782. UINT * errorIndex,
  1783. UINT queryView
  1784. )
  1785. /*++
  1786. Routine Description:
  1787. Adds varbind to query list.
  1788. Arguments:
  1789. tfxInfo - context info.
  1790. vbl - list of varbinds.
  1791. ql - list of subagent queries.
  1792. vb - index of varbind to add to query.
  1793. errorStatus - used to indicate success or failure.
  1794. errorIndex - used to identify an errant varbind.
  1795. queryView - view of query requested.
  1796. Return Values:
  1797. None.
  1798. --*/
  1799. {
  1800. INT i;
  1801. INT nDiff;
  1802. INT lastViewIndex;
  1803. BOOL fAnyOk;
  1804. BOOL fFoundOk = FALSE;
  1805. UINT mibAction;
  1806. SnmpMibView * mibView;
  1807. SnmpMibEntry * mibEntry = NULL;
  1808. SnmpTableXlat * tblXlat = NULL;
  1809. // copy request type
  1810. mibAction = ql->action;
  1811. // determine whether we need exact match
  1812. fAnyOk = (mibAction == MIB_ACTION_GETNEXT);
  1813. SNMPDBG((
  1814. SNMP_LOG_VERBOSE,
  1815. "SNMP: TFX: searching subagents to resolve %s (%s).\n",
  1816. SnmpUtilOidToA(&vbl->list[vb].name),
  1817. fAnyOk ? "AnyOk" : "AnyNOk"
  1818. ));
  1819. SNMPDBG((
  1820. SNMP_LOG_VERBOSE,
  1821. "SNMP: TFX: VarBindToQueryList; scanning views from %d to %d.\n",
  1822. queryView,
  1823. (INT)tfxInfo->numViews
  1824. ));
  1825. // init to NonView
  1826. lastViewIndex = -1;
  1827. // locate appropriate view (starting at queryView)
  1828. for (i = queryView; (i < (INT)tfxInfo->numViews) && !fFoundOk; i++) {
  1829. // retrieve the mib view information
  1830. mibView = tfxInfo->tfxViews[i].mibView;
  1831. // compare root oids
  1832. nDiff = SnmpUtilOidNCmp(
  1833. &vbl->list[vb].name,
  1834. &mibView->viewOid,
  1835. mibView->viewOid.idLength
  1836. );
  1837. // analyze results based on request type
  1838. fFoundOk = (!nDiff || (fAnyOk && (nDiff < 0)));
  1839. SNMPDBG((
  1840. SNMP_LOG_VERBOSE,
  1841. "SNMP: TFX: View %d: comp(%s, ",
  1842. i,
  1843. SnmpUtilOidToA(&vbl->list[vb].name)
  1844. ));
  1845. SNMPDBG((
  1846. SNMP_LOG_VERBOSE,
  1847. "%s, %d) = %d '%s'\n",
  1848. SnmpUtilOidToA(&mibView->viewOid),
  1849. mibView->viewOid.idLength,
  1850. nDiff,
  1851. fFoundOk?"Found":"NotFound"
  1852. ));
  1853. // make sure we can obtain mib entry (if available)
  1854. if (fFoundOk && (mibView->viewType == MIB_VIEW_NORMAL)) {
  1855. // initialize local copy of error status
  1856. UINT mibStatus = SNMP_ERRORSTATUS_NOERROR;
  1857. // store index
  1858. lastViewIndex = i;
  1859. // load mib entry
  1860. VarBindToMibEntry(
  1861. tfxInfo,
  1862. &vbl->list[vb],
  1863. &mibEntry,
  1864. &mibAction,
  1865. &tblXlat,
  1866. i,
  1867. &mibStatus
  1868. );
  1869. SNMPDBG((
  1870. SNMP_LOG_VERBOSE,
  1871. "SNMP: TFX: VarBindToMibEntry returned %d.\n",
  1872. mibStatus
  1873. ));
  1874. // successfully loaded mib entry information
  1875. fFoundOk = (mibStatus == SNMP_ERRORSTATUS_NOERROR);
  1876. // bail if not searching...
  1877. if (!fFoundOk && !fAnyOk) {
  1878. // pass up error status
  1879. *errorStatus = mibStatus;
  1880. *errorIndex = vb+1;
  1881. return; // bail...
  1882. }
  1883. }
  1884. }
  1885. // reset error status and index...
  1886. *errorStatus = SNMP_ERRORSTATUS_NOERROR;
  1887. *errorIndex = 0;
  1888. // found AND had a valid mibEntry
  1889. if (fFoundOk && mibEntry) {
  1890. // save query
  1891. MibEntryToQueryList(
  1892. mibEntry,
  1893. mibAction,
  1894. ql,
  1895. tblXlat,
  1896. i-1,
  1897. vbl,
  1898. vb,
  1899. errorStatus
  1900. );
  1901. } else if (fAnyOk){
  1902. if (lastViewIndex == -1)
  1903. lastViewIndex = tfxInfo->numViews - 1;
  1904. // not supported in any view...
  1905. SnmpUtilOidFree(&vbl->list[vb].name);
  1906. // copy varbind
  1907. if (SnmpUtilOidCpy(
  1908. &vbl->list[vb].name,
  1909. &tfxInfo->tfxViews[lastViewIndex].mibView->viewOid) == 0)
  1910. {
  1911. SNMPDBG((
  1912. SNMP_LOG_ERROR,
  1913. "SNMP: TFX: SnmpUtilOidCpy at line %d failed.\n",
  1914. __LINE__));
  1915. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  1916. return; // bail...
  1917. }
  1918. // increment last element of view oid
  1919. vbl->list[vb].name.ids[(vbl->list[vb].name.idLength-1)]++;
  1920. SNMPDBG((
  1921. SNMP_LOG_VERBOSE,
  1922. "SNMP: TFX: changing varbind to %s.\n",
  1923. SnmpUtilOidToA(&vbl->list[vb].name)
  1924. ));
  1925. }
  1926. }
  1927. VOID
  1928. VarBindListToQueryList(
  1929. SnmpTfxInfo * tfxInfo,
  1930. RFC1157VarBindList * vbl,
  1931. SnmpExtQueryList * ql,
  1932. UINT * errorStatus,
  1933. UINT * errorIndex
  1934. )
  1935. /*++
  1936. Routine Description:
  1937. Convert list of varbinds from incoming pdu into a list of
  1938. individual subagent queries.
  1939. Arguments:
  1940. tfxInfo - context handle.
  1941. vbl - list of varbinds in pdu.
  1942. ql - list of subagent queries.
  1943. errorStatus - used to indicate success or failure.
  1944. errorIndex - used to identify an errant varbind.
  1945. Return Values:
  1946. None.
  1947. --*/
  1948. {
  1949. UINT i; // index into varbind list
  1950. SNMPDBG((
  1951. SNMP_LOG_TRACE,
  1952. "SNMP: TFX: processing %s request containing %d variable(s).\n",
  1953. (ql->action == MIB_ACTION_GET)
  1954. ? "get"
  1955. : (ql->action == MIB_ACTION_SET)
  1956. ? "set"
  1957. : (ql->action == MIB_ACTION_GETNEXT)
  1958. ? "getnext"
  1959. : "unknown", vbl->len));
  1960. // initialize status return values
  1961. *errorStatus = SNMP_ERRORSTATUS_NOERROR;
  1962. *errorIndex = 0;
  1963. // process incoming variable bindings
  1964. for (i=0; i < vbl->len; i++)
  1965. {
  1966. // find varbind
  1967. VarBindToQueryList(
  1968. tfxInfo,
  1969. vbl,
  1970. ql,
  1971. i,
  1972. errorStatus,
  1973. errorIndex,
  1974. 0
  1975. );
  1976. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
  1977. {
  1978. *errorIndex = i+1; // have problem during the processing of (i+1)th varbind
  1979. break;
  1980. }
  1981. }
  1982. }
  1983. UINT
  1984. MibStatusToSnmpStatus(
  1985. UINT mibStatus
  1986. )
  1987. /*++
  1988. Routine Description:
  1989. Translate mib status into snmp error status.
  1990. Arguments:
  1991. mibStatus - mib error code.
  1992. Return Values:
  1993. Returns snmp error status.
  1994. --*/
  1995. {
  1996. UINT errorStatus;
  1997. switch (mibStatus) {
  1998. case MIB_S_SUCCESS:
  1999. errorStatus = SNMP_ERRORSTATUS_NOERROR;
  2000. break;
  2001. case MIB_S_INVALID_PARAMETER:
  2002. errorStatus = SNMP_ERRORSTATUS_BADVALUE;
  2003. break;
  2004. case MIB_S_NOT_SUPPORTED:
  2005. case MIB_S_NO_MORE_ENTRIES:
  2006. case MIB_S_ENTRY_NOT_FOUND:
  2007. errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  2008. break;
  2009. default:
  2010. errorStatus = SNMP_ERRORSTATUS_GENERR;
  2011. break;
  2012. }
  2013. return errorStatus;
  2014. }
  2015. VOID
  2016. AdjustErrorIndex(
  2017. SnmpExtQuery * q,
  2018. UINT * errorIndex
  2019. )
  2020. /*++
  2021. Routine Description:
  2022. Ensure that indices match the original pdu.
  2023. Arguments:
  2024. q - subagent query.
  2025. errorIndex - used to identify an errant varbind.
  2026. Return Values:
  2027. None.
  2028. --*/
  2029. {
  2030. UINT errorIndexOld = *errorIndex;
  2031. // make sure within bounds
  2032. if (errorIndexOld && (errorIndexOld <= q->vblNum)) {
  2033. // determine proper index from xlat info
  2034. *errorIndex = q->vblXlat[errorIndexOld-1].vblIndex+1;
  2035. } else {
  2036. // default to first variable
  2037. *errorIndex = q->vblXlat[0].vblIndex+1;
  2038. }
  2039. }
  2040. BOOL
  2041. ProcessQuery(
  2042. SnmpExtQuery * q,
  2043. UINT * errorStatus,
  2044. UINT * errorIndex
  2045. )
  2046. /*++
  2047. Routine Description:
  2048. Query the subagent for requested items.
  2049. Arguments:
  2050. q - subagent query.
  2051. errorStatus - used to indicate success or failure.
  2052. errorIndex - used to identify an errant varbind.
  2053. Return Values:
  2054. None.
  2055. --*/
  2056. {
  2057. BOOL fOk = TRUE;
  2058. UINT extStatus = 0;
  2059. AsnAny * objArray;
  2060. // validate...
  2061. if (q == NULL) {
  2062. return TRUE;
  2063. }
  2064. // retrieve asn object array
  2065. objArray = (AsnAny *)(q->extData.data);
  2066. SNMPDBG((
  2067. SNMP_LOG_VERBOSE,
  2068. "SNMP: TFX: ProcessQuery - objArray=%lx\n",
  2069. objArray
  2070. ));
  2071. __try {
  2072. SNMPDBG((
  2073. SNMP_LOG_VERBOSE,
  2074. "SNMP: TFX: entering subagent code ....\n"
  2075. ));
  2076. // query subagent
  2077. extStatus = (UINT)(*q->extFunc)(
  2078. q->mibAction,
  2079. objArray,
  2080. errorIndex
  2081. );
  2082. SNMPDBG((
  2083. SNMP_LOG_VERBOSE,
  2084. "SNMP: TFX: ... subagent code completed.\n"
  2085. ));
  2086. SNMPDBG((
  2087. SNMP_LOG_TRACE,
  2088. "SNMP: TFX: subagent returned %s (e=0x%08lx,i=%d).\n",
  2089. (extStatus == MIB_S_SUCCESS)
  2090. ? "MIB_S_SUCCESS"
  2091. : (extStatus == MIB_S_NO_MORE_ENTRIES)
  2092. ? "MIB_S_NO_MORE_ENTRIES"
  2093. : (extStatus == MIB_S_ENTRY_NOT_FOUND)
  2094. ? "MIB_S_ENTRY_NOT_FOUND"
  2095. : (extStatus == MIB_S_INVALID_PARAMETER)
  2096. ? "MIB_S_INVALID_PARAMETER"
  2097. : (extStatus == MIB_S_NOT_SUPPORTED)
  2098. ? "MIB_S_NOT_SUPPORTED"
  2099. : "error", extStatus, *errorIndex
  2100. ));
  2101. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2102. // report exception code
  2103. extStatus = GetExceptionCode();
  2104. // disable
  2105. fOk = FALSE;
  2106. }
  2107. // save error info
  2108. SetLastError(extStatus);
  2109. // pass back translated version
  2110. *errorStatus = MibStatusToSnmpStatus(extStatus);
  2111. return fOk;
  2112. }
  2113. VOID
  2114. ProcessQueryList(
  2115. SnmpTfxInfo * tfxInfo,
  2116. SnmpExtQueryList * ql,
  2117. RFC1157VarBindList * vbl,
  2118. UINT * errorStatus,
  2119. UINT * errorIndex
  2120. )
  2121. /*++
  2122. Routine Description:
  2123. Process the query list based on request type.
  2124. Arguments:
  2125. tfxInfo - context information.
  2126. ql - list of subagent queries.
  2127. vbl - list of incoming variable bindings.
  2128. errorStatus - used to indicate success or failure.
  2129. errorIndex - used to identify an errant varbind.
  2130. Return Values:
  2131. None.
  2132. --*/
  2133. {
  2134. INT i=0; // index into query list
  2135. INT j=0; // index into query list
  2136. INT qlLen = ql->len; // save...
  2137. SNMPDBG((
  2138. SNMP_LOG_TRACE,
  2139. "SNMP: TFX: processing %d subagent queries.\n",
  2140. qlLen
  2141. ));
  2142. // sets are processed below...
  2143. if (ql->action != MIB_ACTION_SET) {
  2144. // process list of individual queries
  2145. for (i=0; (i < qlLen) && !(*errorStatus); i++ ) {
  2146. // send query to subagent
  2147. if (ProcessQuery(&ql->query[i], errorStatus, errorIndex)) {
  2148. // need to validate getnext results
  2149. if (ql->action == MIB_ACTION_GETNEXT) {
  2150. // exhaust all possibilities...
  2151. ValidateQueryList(
  2152. tfxInfo,
  2153. ql,
  2154. i,
  2155. vbl,
  2156. errorStatus,
  2157. errorIndex
  2158. );
  2159. }
  2160. // check the subagent status code returned
  2161. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
  2162. // adjust index to match request pdu
  2163. AdjustErrorIndex(&ql->query[i], errorIndex);
  2164. }
  2165. } else {
  2166. // subagent unable to process query
  2167. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2168. *errorIndex = 1;
  2169. // adjust index to match request pdu
  2170. AdjustErrorIndex(&ql->query[i], errorIndex);
  2171. }
  2172. }
  2173. } else {
  2174. // process all of the validate queries
  2175. for (i=0; (i < qlLen) && !(*errorStatus); i++) {
  2176. // alter query type to validate entries
  2177. ql->query[i].mibAction = MIB_ACTION_VALIDATE;
  2178. // send query to subagent
  2179. if (ProcessQuery(&ql->query[i], errorStatus, errorIndex)) {
  2180. // check the subagent status code returned
  2181. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
  2182. // adjust index to match request pdu
  2183. AdjustErrorIndex(&ql->query[i], errorIndex);
  2184. }
  2185. } else {
  2186. // subagent unable to process query
  2187. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2188. *errorIndex = 1;
  2189. // adjust index to match request pdu
  2190. AdjustErrorIndex(&ql->query[i], errorIndex);
  2191. }
  2192. }
  2193. // process all of the set queries
  2194. for (j=0; (j < qlLen) && !(*errorStatus); j++) {
  2195. // alter query type to set entries
  2196. ql->query[j].mibAction = MIB_ACTION_SET;
  2197. // send query to subagent
  2198. if (ProcessQuery(&ql->query[j], errorStatus, errorIndex)) {
  2199. // check the subagent status code returned
  2200. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
  2201. // adjust index to match request pdu
  2202. AdjustErrorIndex(&ql->query[j], errorIndex);
  2203. }
  2204. } else {
  2205. // subagent unable to process query
  2206. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2207. *errorIndex = 1;
  2208. // adjust index to match request pdu
  2209. AdjustErrorIndex(&ql->query[j], errorIndex);
  2210. }
  2211. }
  2212. // cleanup...
  2213. while (i-- > 0) {
  2214. UINT ignoreStatus = 0; // dummy values
  2215. UINT ignoreIndex = 0; // dummy values
  2216. // alter query type to set entries
  2217. ql->query[i].mibAction = MIB_ACTION_CLEANUP;
  2218. // send the cleanup request success or not
  2219. ProcessQuery(&ql->query[i], &ignoreStatus, &ignoreIndex);
  2220. }
  2221. }
  2222. }
  2223. BOOL
  2224. ConstructInstanceIdentifier(
  2225. SnmpTableXlat * tblXlat,
  2226. AsnAny * objArray,
  2227. AsnObjectIdentifier * newOid,
  2228. UINT mibAction
  2229. )
  2230. /*++
  2231. Routine Description:
  2232. Convert asn value into index oid.
  2233. Arguments:
  2234. tblXlat - table translation info.
  2235. objArray - asn object array.
  2236. newOid - relative oid to return.
  2237. mibAction - action requested of subagent.
  2238. Return Values: TRUE if successful
  2239. None.
  2240. --*/
  2241. {
  2242. UINT i;
  2243. UINT j;
  2244. UINT k;
  2245. UINT l;
  2246. UINT m;
  2247. BOOL fFixed;
  2248. BOOL fLimit;
  2249. BOOL fIndex;
  2250. UINT numItems;
  2251. SnmpMibEntry * mibEntry;
  2252. UINT * tmpIds = NULL; // prefix bug 445170
  2253. // initialize
  2254. newOid->ids = NULL;
  2255. newOid->idLength = 0;
  2256. SNMPDBG((
  2257. SNMP_LOG_TRACE,
  2258. "SNMP: TFX: converting obj array to index via table 0x%08lx.\n",
  2259. tblXlat->txInfo
  2260. ));
  2261. // retrieve root entry and entry count
  2262. numItems = tblXlat->txInfo->numIndices;
  2263. // see if the table indices are specified
  2264. fIndex = (tblXlat->txInfo->tableIndices != NULL);
  2265. // scan entries of table indices
  2266. for (i=0, j=0; i < numItems; i++) {
  2267. // get mib entry from table or directly
  2268. mibEntry = fIndex ? tblXlat->txInfo->tableIndices[i]
  2269. : &tblXlat->txInfo->tableEntry[i+1]
  2270. ;
  2271. // retrieve array index
  2272. k = (mibAction == MIB_ACTION_SET)
  2273. ? (UINT)(CHAR)mibEntry->mibSetBufOff
  2274. : (UINT)(CHAR)mibEntry->mibGetBufOff
  2275. ;
  2276. SNMPDBG((
  2277. SNMP_LOG_TRACE,
  2278. "SNMP: TFX: ConstructIndexIdentifier - k=%d\n",
  2279. k
  2280. ));
  2281. // determine type
  2282. switch (mibEntry->mibType) {
  2283. // variable length types
  2284. case ASN_OBJECTIDENTIFIER:
  2285. // check whether this is a fixed length variable or not
  2286. fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
  2287. fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
  2288. // validate
  2289. if (fFixed) {
  2290. // fixed length
  2291. l = mibEntry->mibMaximum;
  2292. // allocate space
  2293. newOid->idLength += l;
  2294. tmpIds = (UINT *)SnmpUtilMemReAlloc(
  2295. newOid->ids,
  2296. newOid->idLength * sizeof(UINT)
  2297. );
  2298. if (tmpIds == NULL)
  2299. {
  2300. newOid->idLength = 0;
  2301. SnmpUtilMemFree(newOid->ids);
  2302. newOid->ids = NULL;
  2303. return FALSE;
  2304. }
  2305. newOid->ids = tmpIds;
  2306. } else {
  2307. // determine variable length of object
  2308. l = objArray[k].asnValue.object.idLength;
  2309. // allocate space
  2310. newOid->idLength += (l+1);
  2311. tmpIds = (UINT *)SnmpUtilMemReAlloc(
  2312. newOid->ids,
  2313. newOid->idLength * sizeof(UINT)
  2314. );
  2315. if (tmpIds == NULL)
  2316. {
  2317. newOid->idLength = 0;
  2318. SnmpUtilMemFree(newOid->ids);
  2319. newOid->ids = NULL;
  2320. return FALSE;
  2321. }
  2322. newOid->ids = tmpIds;
  2323. // save length
  2324. newOid->ids[j++] = l;
  2325. }
  2326. // transfer data
  2327. for (m=0; m < l; m++) {
  2328. // transfer oid element from buffer
  2329. newOid->ids[j++] = objArray[k].asnValue.object.ids[m];
  2330. }
  2331. break;
  2332. case ASN_RFC1155_OPAQUE:
  2333. case ASN_OCTETSTRING:
  2334. // check whether this is a fixed length variable or not
  2335. fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
  2336. fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
  2337. // validate
  2338. if (fFixed) {
  2339. // fixed length
  2340. l = mibEntry->mibMaximum;
  2341. // allocate space
  2342. newOid->idLength += l;
  2343. tmpIds = (UINT *)SnmpUtilMemReAlloc(
  2344. newOid->ids,
  2345. newOid->idLength * sizeof(UINT)
  2346. );
  2347. if (tmpIds == NULL)
  2348. {
  2349. newOid->idLength = 0;
  2350. SnmpUtilMemFree(newOid->ids);
  2351. newOid->ids = NULL;
  2352. return FALSE;
  2353. }
  2354. newOid->ids = tmpIds;
  2355. } else {
  2356. // determine variable length of object
  2357. l = objArray[k].asnValue.string.length;
  2358. // allocate space
  2359. newOid->idLength += (l+1);
  2360. tmpIds = (UINT *)SnmpUtilMemReAlloc(
  2361. newOid->ids,
  2362. newOid->idLength * sizeof(UINT)
  2363. );
  2364. if (tmpIds == NULL)
  2365. {
  2366. newOid->idLength = 0;
  2367. SnmpUtilMemFree(newOid->ids);
  2368. newOid->ids = NULL;
  2369. return FALSE;
  2370. }
  2371. newOid->ids = tmpIds;
  2372. // save length
  2373. newOid->ids[j++] = l;
  2374. }
  2375. // transfer data
  2376. for (m=0; m < l; m++) {
  2377. // convert character
  2378. newOid->ids[j++] =
  2379. (UINT)(UCHAR)objArray[k].asnValue.string.stream[m];
  2380. }
  2381. break;
  2382. // implicit fixed size
  2383. case ASN_RFC1155_IPADDRESS:
  2384. // allocate space
  2385. newOid->idLength += 4;
  2386. tmpIds = (UINT *)SnmpUtilMemReAlloc(
  2387. newOid->ids,
  2388. newOid->idLength * sizeof(UINT)
  2389. );
  2390. if (tmpIds == NULL)
  2391. {
  2392. newOid->idLength = 0;
  2393. SnmpUtilMemFree(newOid->ids);
  2394. newOid->ids = NULL;
  2395. return FALSE;
  2396. }
  2397. newOid->ids = tmpIds;
  2398. // transfer data into buffer
  2399. newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[0];
  2400. newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[1];
  2401. newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[2];
  2402. newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[3];
  2403. break;
  2404. case ASN_RFC1155_COUNTER:
  2405. case ASN_RFC1155_GAUGE:
  2406. case ASN_RFC1155_TIMETICKS:
  2407. case ASN_INTEGER:
  2408. // allocate space
  2409. newOid->idLength += 1;
  2410. tmpIds = (UINT *)SnmpUtilMemReAlloc(
  2411. newOid->ids,
  2412. newOid->idLength * sizeof(UINT)
  2413. );
  2414. if (tmpIds == NULL)
  2415. {
  2416. newOid->idLength = 0;
  2417. SnmpUtilMemFree(newOid->ids);
  2418. newOid->ids = NULL;
  2419. return FALSE;
  2420. }
  2421. newOid->ids = tmpIds;
  2422. // transfer value as integer
  2423. newOid->ids[j++] = objArray[k].asnValue.number;
  2424. break;
  2425. default:
  2426. // invalidate
  2427. j = INVALID_INDEX;
  2428. break;
  2429. }
  2430. }
  2431. return TRUE;
  2432. }
  2433. VOID
  2434. DeleteQuery(
  2435. SnmpExtQuery * q
  2436. )
  2437. /*++
  2438. Routine Description:
  2439. Deletes individual query.
  2440. Arguments:
  2441. q - subagent query.
  2442. Return Values:
  2443. None.
  2444. --*/
  2445. {
  2446. UINT i; // index into xlat array
  2447. UINT j; // index into object array
  2448. BOOL fSet;
  2449. AsnAny * objArray;
  2450. SnmpMibEntry * mibEntry;
  2451. SNMPDBG((
  2452. SNMP_LOG_VERBOSE,
  2453. "SNMP: TFX: deleting query 0x%08lx.\n", q
  2454. ));
  2455. // determine whether a set was requested
  2456. fSet = (q->mibAction == MIB_ACTION_SET);
  2457. // retrieve asn object array
  2458. objArray = (AsnAny *)(q->extData.data);
  2459. // free requested entries
  2460. for (i = 0; i < q->vblNum; i++ )
  2461. {
  2462. // retrieve mib entry
  2463. mibEntry = q->vblXlat[i].mibEntry;
  2464. ASSERT(mibEntry);
  2465. j = fSet ? (UINT)(CHAR)mibEntry->mibSetBufOff
  2466. : (UINT)(CHAR)mibEntry->mibGetBufOff
  2467. ;
  2468. if (objArray)
  2469. SnmpUtilAsnAnyFree(&objArray[j]);
  2470. // free any followup queries
  2471. if ((q->vblXlat[i].extQuery != NULL) &&
  2472. (q->vblXlat[i].extQuery != INVALID_QUERY))
  2473. {
  2474. SNMPDBG((
  2475. SNMP_LOG_VERBOSE,
  2476. "SNMP: TFX: deleting followup query 0x%08lx.\n",
  2477. q->vblXlat[i].extQuery
  2478. ));
  2479. // free followup query
  2480. DeleteQuery(q->vblXlat[i].extQuery);
  2481. // free query structure itself
  2482. SnmpUtilMemFree(q->vblXlat[i].extQuery);
  2483. }
  2484. }
  2485. q->vblNum = 0;
  2486. // free indices
  2487. if (q->tblXlat && objArray)
  2488. {
  2489. BOOL fIndex;
  2490. // see if the table indices are specified
  2491. fIndex = (q->tblXlat->txInfo->tableIndices != NULL);
  2492. // free the individual indices
  2493. for (i = 0; i < q->tblXlat->txInfo->numIndices; i++)
  2494. {
  2495. // get mib entry from table or directly from entry
  2496. mibEntry = fIndex ? q->tblXlat->txInfo->tableIndices[i]
  2497. : &q->tblXlat->txInfo->tableEntry[i+1]
  2498. ;
  2499. ASSERT(mibEntry);
  2500. // determine the buffer offset used
  2501. j = fSet ? (UINT)(CHAR)mibEntry->mibSetBufOff
  2502. : (UINT)(CHAR)mibEntry->mibGetBufOff
  2503. ;
  2504. // free individual index
  2505. SnmpUtilAsnAnyFree(&objArray[j]);
  2506. }
  2507. }
  2508. // free buffer
  2509. SnmpUtilMemFree(objArray);
  2510. // avoid double freeing
  2511. q->extData.data = NULL;
  2512. // free table info
  2513. if (q->tblXlat) {
  2514. // free object identifier
  2515. SnmpUtilOidFree(&q->tblXlat->txOid);
  2516. // free the xlat structure
  2517. SnmpUtilMemFree(q->tblXlat);
  2518. // avoid double freeing
  2519. q->tblXlat = NULL;
  2520. }
  2521. // free translation info
  2522. SnmpUtilMemFree(q->vblXlat);
  2523. // avoid double freeing
  2524. q->vblXlat = NULL;
  2525. }
  2526. VOID
  2527. DeleteQueryList(
  2528. SnmpExtQueryList * ql
  2529. )
  2530. /*++
  2531. Routine Description:
  2532. Deletes query list.
  2533. Arguments:
  2534. ql - list of subagent queries.
  2535. Return Values:
  2536. None.
  2537. --*/
  2538. {
  2539. UINT q; // index into query list
  2540. // process queries
  2541. for (q=0; q < ql->len; q++) {
  2542. // delete query
  2543. DeleteQuery(&ql->query[q]);
  2544. }
  2545. // free query list
  2546. SnmpUtilMemFree(ql->query);
  2547. }
  2548. VOID
  2549. QueryToVarBindList(
  2550. SnmpTfxInfo * tfxInfo,
  2551. SnmpExtQuery * q,
  2552. RFC1157VarBindList * vbl,
  2553. UINT * errorStatus,
  2554. UINT * errorIndex
  2555. )
  2556. /*++
  2557. Routine Description:
  2558. Convert query back into varbind.
  2559. Arguments:
  2560. tfxInfo - context info
  2561. q - subagent query.
  2562. vbl - list of varbinds in outgoing pdu.
  2563. Return Values:
  2564. None.
  2565. --*/
  2566. {
  2567. UINT i=0;
  2568. UINT j=0;
  2569. UINT k=0;
  2570. UINT l=0;
  2571. BOOL fSet;
  2572. AsnAny * objArray;
  2573. SnmpMibEntry * mibEntry;
  2574. AsnObjectIdentifier idxOid;
  2575. SNMPDBG((
  2576. SNMP_LOG_VERBOSE,
  2577. "SNMP: TFX: converting query 0x%08lx to varbinds.\n", q
  2578. ));
  2579. // determine whether a set was requested
  2580. fSet = (q->mibAction == MIB_ACTION_SET);
  2581. // retrieve asn object array
  2582. objArray = (AsnAny *)(q->extData.data);
  2583. // copy requested entries
  2584. for (j = 0; j < q->vblNum; j++) {
  2585. // process followup query
  2586. if (q->vblXlat[j].extQuery != NULL) {
  2587. if (q->vblXlat[j].extQuery != INVALID_QUERY) {
  2588. SNMPDBG((
  2589. SNMP_LOG_VERBOSE,
  2590. "SNMP: TFX: processing followup query 0x%08lx.\n",
  2591. q->vblXlat[j].extQuery
  2592. ));
  2593. QueryToVarBindList(
  2594. tfxInfo,
  2595. q->vblXlat[j].extQuery,
  2596. vbl,
  2597. errorStatus,
  2598. errorIndex
  2599. );
  2600. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
  2601. return; // bail...
  2602. else
  2603. continue; // skip...
  2604. } else {
  2605. i = q->vblXlat[j].vblIndex;
  2606. SNMPDBG((
  2607. SNMP_LOG_TRACE,
  2608. "SNMP: TFX: returning oid %s without reassembly.\n",
  2609. SnmpUtilOidToA(&vbl->list[i].name)
  2610. ));
  2611. continue; // skip...
  2612. }
  2613. }
  2614. // retrieve index
  2615. i = q->vblXlat[j].vblIndex;
  2616. // retrieve mib entry for requested item
  2617. mibEntry = q->vblXlat[j].mibEntry;
  2618. k = fSet ? (UINT)(CHAR)mibEntry->mibSetBufOff
  2619. : (UINT)(CHAR)mibEntry->mibGetBufOff
  2620. ;
  2621. // free original variable
  2622. SnmpUtilVarBindFree(&vbl->list[i]);
  2623. // copy the asn value first
  2624. if (SnmpUtilAsnAnyCpy(&vbl->list[i].value, &objArray[k]) == 0)
  2625. {
  2626. // report memory allocation problem
  2627. *errorIndex = i+1; // failed in (i+1)th varbind
  2628. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2629. SNMPDBG((
  2630. SNMP_LOG_ERROR,
  2631. "SNMP: TFX: SnmpUtilAsnAnyCpy at line %d failed on the %d th varbind.\n",
  2632. __LINE__, i+1
  2633. ));
  2634. return; // bail...
  2635. }
  2636. // copy root oid of view
  2637. if (SnmpUtilOidCpy(
  2638. &vbl->list[i].name,
  2639. &tfxInfo->tfxViews[(q->vblXlat[j].vlIndex)].mibView->viewOid) == 0)
  2640. {
  2641. // report memory allocation problem
  2642. *errorIndex = i+1; // failed in (i+1)th varbind
  2643. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2644. SNMPDBG((
  2645. SNMP_LOG_ERROR,
  2646. "SNMP: TFX: SnmpUtilOidCpy at line %d failed on the %d th varbind.\n",
  2647. __LINE__, i+1
  2648. ));
  2649. return; // bail...
  2650. }
  2651. // copy oid of variable
  2652. if (SnmpUtilOidAppend(
  2653. &vbl->list[i].name,
  2654. &mibEntry->mibOid) == 0)
  2655. {
  2656. // report memory allocation problem
  2657. *errorIndex = i+1; // failed in (i+1)th varbind
  2658. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2659. SNMPDBG((
  2660. SNMP_LOG_ERROR,
  2661. "SNMP: TFX: SnmpUtilOidAppend at line %d failed on the %d th varbind.\n",
  2662. __LINE__, i+1
  2663. ));
  2664. return; // bail...
  2665. }
  2666. // copy table index
  2667. if (q->tblXlat) {
  2668. // convert value to oid
  2669. if (ConstructInstanceIdentifier(q->tblXlat, objArray, &idxOid, q->mibAction) == FALSE)
  2670. {
  2671. // report memory allocation problem
  2672. *errorIndex = i+1; // failed in (i+1)th varbind
  2673. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2674. SNMPDBG((
  2675. SNMP_LOG_ERROR,
  2676. "SNMP: TFX: ConstructInstanceIdentifier failed with %d th varbind.\n",
  2677. i+1
  2678. ));
  2679. return; // bail...
  2680. }
  2681. // append oid to object name
  2682. if (SnmpUtilOidAppend(&vbl->list[i].name, &idxOid) == 0)
  2683. {
  2684. // free temp oid
  2685. SnmpUtilOidFree(&idxOid);
  2686. // report memory allocation problem
  2687. *errorIndex = i+1; // failed in (i+1)th varbind
  2688. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2689. SNMPDBG((
  2690. SNMP_LOG_ERROR,
  2691. "SNMP: TFX: SnmpUtilOidAppend at line %d failed on the %d th varbind.\n",
  2692. __LINE__, i+1
  2693. ));
  2694. return; // bail...
  2695. }
  2696. // free temp oid
  2697. SnmpUtilOidFree(&idxOid);
  2698. }
  2699. SNMPDBG((
  2700. SNMP_LOG_TRACE,
  2701. "SNMP: TFX: returning oid %s.\n",
  2702. SnmpUtilOidToA(&vbl->list[i].name)
  2703. ));
  2704. }
  2705. }
  2706. VOID
  2707. QueryListToVarBindList(
  2708. SnmpTfxInfo * tfxInfo,
  2709. SnmpExtQueryList * ql,
  2710. RFC1157VarBindList * vbl,
  2711. UINT * errorStatus,
  2712. UINT * errorIndex
  2713. )
  2714. /*++
  2715. Routine Description:
  2716. Convert query list back into outgoing varbinds.
  2717. Arguments:
  2718. tfxInfo - context information.
  2719. ql - list of subagent queries.
  2720. vbl - list of varbinds in outgoing pdu.
  2721. errorStatus - used to indicate success or failure.
  2722. errorIndex - used to identify an errant varbind.
  2723. Return Values:
  2724. None.
  2725. --*/
  2726. {
  2727. UINT q; // index into queue list
  2728. UINT vb; // index into queue varbind list
  2729. UINT i; // index into original varbind list
  2730. SNMPDBG((
  2731. SNMP_LOG_TRACE,
  2732. "SNMP: TFX: request %s, errorStatus=%s, errorIndex=%d.\n",
  2733. (*errorStatus == SNMP_ERRORSTATUS_NOERROR)
  2734. ? "succeeded"
  2735. : "failed",
  2736. (*errorStatus == SNMP_ERRORSTATUS_NOERROR)
  2737. ? "NOERROR"
  2738. : (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME)
  2739. ? "NOSUCHNAME"
  2740. : (*errorStatus == SNMP_ERRORSTATUS_BADVALUE)
  2741. ? "BADVALUE"
  2742. : (*errorStatus == SNMP_ERRORSTATUS_READONLY)
  2743. ? "READONLY"
  2744. : (*errorStatus == SNMP_ERRORSTATUS_TOOBIG)
  2745. ? "TOOBIG"
  2746. : "GENERR", *errorIndex
  2747. ));
  2748. // only convert back if error not reported
  2749. if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
  2750. // process queries
  2751. for (q=0; q < ql->len; q++) {
  2752. // translate query data
  2753. QueryToVarBindList(tfxInfo, &ql->query[q], vbl, errorStatus, errorIndex);
  2754. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
  2755. break;
  2756. }
  2757. }
  2758. // free
  2759. DeleteQueryList(ql);
  2760. }
  2761. VOID
  2762. ValidateQueryList(
  2763. SnmpTfxInfo * tfxInfo,
  2764. SnmpExtQueryList * ql,
  2765. UINT q,
  2766. RFC1157VarBindList * vbl,
  2767. UINT * errorStatus,
  2768. UINT * errorIndex
  2769. )
  2770. /*++
  2771. Routine Description:
  2772. Validate getnext results and re-query if necessary.
  2773. Arguments:
  2774. tfxInfo - context information.
  2775. ql - list of subagent queries.
  2776. q - subagent query of interest.
  2777. vbl - list of bindings in incoming pdu.
  2778. errorStatus - used to indicate success or failure.
  2779. errorIndex - used to identify an errant varbind.
  2780. Return Values:
  2781. None.
  2782. --*/
  2783. {
  2784. UINT i;
  2785. UINT j;
  2786. SnmpExtQueryList tmpQl;
  2787. UINT vlIndex;
  2788. UINT vblIndex;
  2789. UINT mibAction;
  2790. UINT mibStatus;
  2791. SnmpMibEntry * mibEntry;
  2792. SnmpTableXlat * tblXlat;
  2793. RFC1157VarBindList tmpVbl;
  2794. BOOL fFoundOk = FALSE;
  2795. SNMPDBG((
  2796. SNMP_LOG_TRACE,
  2797. "SNMP: TFX: verifying results of query 0x%08lx.\n", &ql->query[q]
  2798. ));
  2799. // bail on any error other than no such name
  2800. if (*errorStatus != SNMP_ERRORSTATUS_NOSUCHNAME) {
  2801. SNMPDBG((
  2802. SNMP_LOG_TRACE,
  2803. "SNMP: TFX: *errorStatus != SNMP_ERRORSTATUS_NOSUCHNAME, *errorStatus = %d.\n",
  2804. *errorStatus
  2805. ));
  2806. return; // bail...
  2807. }
  2808. // scan query list updating variables
  2809. for (i=0; i < ql->query[q].vblNum; i++) {
  2810. // initialize
  2811. mibEntry = ql->query[q].vblXlat[i].mibEntry;
  2812. vlIndex = ql->query[q].vblXlat[i].vlIndex;
  2813. j = ql->query[q].vblXlat[i].vlIndex;
  2814. tblXlat = NULL;
  2815. mibAction = MIB_ACTION_GETNEXT;
  2816. SNMPDBG((
  2817. SNMP_LOG_TRACE,
  2818. "SNMP: TFX: ValidateQueryList; next of %s.\n",
  2819. SnmpUtilOidToA(&mibEntry->mibOid)
  2820. ));
  2821. // next...
  2822. FindNextMibEntry(
  2823. tfxInfo,
  2824. NULL,
  2825. &mibEntry,
  2826. &mibAction,
  2827. &tblXlat,
  2828. vlIndex,
  2829. errorStatus
  2830. );
  2831. while (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
  2832. SNMPDBG((
  2833. SNMP_LOG_TRACE,
  2834. "SNMP: TFX: constructing followup to query 0x%08lx:\n"
  2835. "SNMP: TFX: \tmibEntry=0x%08lx\n"
  2836. "SNMP: TFX: \ttblXlat =0x%08lx\n",
  2837. &ql->query[q],
  2838. mibEntry,
  2839. tblXlat
  2840. ));
  2841. // initialize
  2842. tmpQl.len = 0;
  2843. tmpQl.query = NULL;
  2844. tmpQl.action = MIB_ACTION_GETNEXT;
  2845. // create query
  2846. MibEntryToQueryList(
  2847. mibEntry,
  2848. mibAction,
  2849. &tmpQl,
  2850. tblXlat,
  2851. vlIndex,
  2852. NULL,
  2853. ql->query[q].vblXlat[i].vblIndex,
  2854. errorStatus
  2855. );
  2856. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
  2857. SNMPDBG((
  2858. SNMP_LOG_ERROR,
  2859. "SNMP: TFX: ValidateQueryList; MibEntryToQueryList returned %d.\n",
  2860. *errorStatus
  2861. ));
  2862. // delete if necessary
  2863. DeleteQueryList(&tmpQl);
  2864. return; // bail...
  2865. }
  2866. SNMPDBG((
  2867. SNMP_LOG_TRACE,
  2868. "SNMP: TFX: processing followup query 0x%08lx.\n",
  2869. tmpQl.query
  2870. ));
  2871. // perform query with new oid
  2872. ProcessQuery(tmpQl.query, errorStatus, errorIndex);
  2873. // calculate results of query
  2874. if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
  2875. SNMPDBG((
  2876. SNMP_LOG_TRACE,
  2877. "SNMP: TFX: saving followup 0x%08lx in query 0x%08lx.\n",
  2878. tmpQl.query, &ql->query[q]
  2879. ));
  2880. // copy query for reassembly purposes
  2881. ql->query[q].vblXlat[i].extQuery = tmpQl.query;
  2882. break; // process next varbind...
  2883. } else if (*errorStatus != SNMP_ERRORSTATUS_NOSUCHNAME) {
  2884. SNMPDBG((
  2885. SNMP_LOG_TRACE,
  2886. "SNMP: TFX: could not process followup.\n"
  2887. ));
  2888. // delete...
  2889. DeleteQueryList(&tmpQl);
  2890. return; // bail...
  2891. }
  2892. SNMPDBG((
  2893. SNMP_LOG_TRACE,
  2894. "SNMP: TFX: re-processing followup to query 0x%08lx.\n",
  2895. &ql->query[q]
  2896. ));
  2897. // delete...
  2898. DeleteQueryList(&tmpQl);
  2899. // re-initialize and continue...
  2900. *errorStatus = SNMP_ERRORSTATUS_NOERROR;
  2901. tblXlat = NULL;
  2902. mibAction = MIB_ACTION_GETNEXT;
  2903. // next...
  2904. FindNextMibEntry(
  2905. tfxInfo,
  2906. NULL,
  2907. &mibEntry,
  2908. &mibAction,
  2909. &tblXlat,
  2910. vlIndex,
  2911. errorStatus
  2912. );
  2913. }
  2914. // NOTE: if we break from the above while loop,
  2915. // *errorStatus will be SNMP_ERRORSTATUS_NOERROR
  2916. // attempt to query next supported subagent view
  2917. if (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME) {
  2918. // retrieve variable binding list index
  2919. vblIndex = ql->query[q].vblXlat[i].vblIndex;
  2920. // release old variable binding
  2921. SnmpUtilVarBindFree(&vbl->list[vblIndex]);
  2922. // copy varbind
  2923. if (! SnmpUtilOidCpy(&vbl->list[vblIndex].name,
  2924. &tfxInfo->tfxViews[j].mibView->viewOid) )
  2925. {
  2926. SNMPDBG((
  2927. SNMP_LOG_ERROR,
  2928. "SNMP: TFX: ValidateQueryList; SnmpUtilOidCpy failed.\n"
  2929. ));
  2930. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  2931. return; // bail...
  2932. }
  2933. // increment last sub-identifier of view oid
  2934. vbl->list[vblIndex].name.ids[vbl->list[vblIndex].name.idLength-1]++;
  2935. SNMPDBG((
  2936. SNMP_LOG_TRACE,
  2937. "SNMP: TFX: query out of view. Pass up %s to service.\n",
  2938. SnmpUtilOidToA(&vbl->list[vblIndex].name)
  2939. ));
  2940. // this query goes outside the MIB view.
  2941. // varbind is set (above) to the first OID outside this view, so let the master agent
  2942. // handle the switch between views.
  2943. // let QueryToVarBindList() knows that this SnmpVarBindXlat is
  2944. // not valid for reassembly purpose.
  2945. ql->query[q].vblXlat[i].extQuery = INVALID_QUERY;
  2946. *errorStatus = SNMP_ERRORSTATUS_NOERROR;
  2947. continue; // process next varbind...
  2948. } else if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
  2949. SNMPDBG((
  2950. SNMP_LOG_ERROR,
  2951. "SNMP: TFX: ValidateQueryList; FindNextMibEntry returned %d.\n",
  2952. *errorStatus
  2953. ));
  2954. return; // bail...
  2955. }
  2956. }
  2957. }
  2958. SnmpTfxInfo *
  2959. AllocTfxInfo(
  2960. )
  2961. {
  2962. // simply return results from generic memory allocation
  2963. return (SnmpTfxInfo *)SnmpUtilMemAlloc(sizeof(SnmpTfxInfo));
  2964. }
  2965. VOID
  2966. FreeTfxInfo(
  2967. SnmpTfxInfo * tfxInfo
  2968. )
  2969. {
  2970. UINT i;
  2971. // prefix bug 445171
  2972. if (tfxInfo == NULL) {
  2973. return;
  2974. }
  2975. if (tfxInfo->tfxViews == NULL)
  2976. {
  2977. SnmpUtilMemFree(tfxInfo);
  2978. return;
  2979. }
  2980. // walk through list of views
  2981. for (i=0; (i < tfxInfo->numViews); i++) {
  2982. // release memory for view hash tables
  2983. FreeHashTable(tfxInfo->tfxViews[i].hashTable);
  2984. }
  2985. SnmpUtilMemFree(tfxInfo->tfxViews);
  2986. SnmpUtilMemFree(tfxInfo);
  2987. }
  2988. ///////////////////////////////////////////////////////////////////////////////
  2989. // //
  2990. // Public Procedures //
  2991. // //
  2992. ///////////////////////////////////////////////////////////////////////////////
  2993. SnmpTfxHandle
  2994. SNMP_FUNC_TYPE
  2995. SnmpTfxOpen(
  2996. DWORD numViews,
  2997. SnmpMibView * supportedViews
  2998. )
  2999. {
  3000. UINT i,j;
  3001. BOOL fOk;
  3002. SnmpTfxInfo * tfxInfo = NULL;
  3003. // validate parameters
  3004. if ((numViews == 0) ||
  3005. (supportedViews == NULL)) {
  3006. return NULL;
  3007. }
  3008. // allocate structure
  3009. tfxInfo = AllocTfxInfo();
  3010. // validate pointer
  3011. if (tfxInfo == NULL) {
  3012. return NULL;
  3013. }
  3014. // copy number of views
  3015. tfxInfo->numViews = numViews;
  3016. // allocate individual view structures
  3017. tfxInfo->tfxViews = SnmpUtilMemAlloc(
  3018. tfxInfo->numViews * sizeof(SnmpTfxView)
  3019. );
  3020. // initialize status
  3021. fOk = (tfxInfo->tfxViews != NULL);
  3022. // initialize each view structure
  3023. for (i=0; (i < tfxInfo->numViews) && fOk; i++) {
  3024. SnmpHashNode ** tmpHashTable;
  3025. // initialize individual view list entry
  3026. tmpHashTable = AllocHashTable(&supportedViews[i]);
  3027. // initialize status
  3028. fOk = (tmpHashTable != NULL);
  3029. // validate
  3030. if (fOk) {
  3031. // save a pointer into the subagent view list
  3032. tfxInfo->tfxViews[i].mibView = &supportedViews[i];
  3033. // save newly allocated view hash table
  3034. tfxInfo->tfxViews[i].hashTable = tmpHashTable;
  3035. }
  3036. }
  3037. // validate
  3038. if (fOk) {
  3039. SnmpTfxView tmpTfxView;
  3040. // make sure views are sorted
  3041. for (i=0; (i < tfxInfo->numViews); i++) {
  3042. for(j=i+1; (j < tfxInfo->numViews); j++) {
  3043. // in lexographic order?
  3044. if (0 < SnmpUtilOidCmp(
  3045. &(tfxInfo->tfxViews[i].mibView->viewOid),
  3046. &(tfxInfo->tfxViews[j].mibView->viewOid))) {
  3047. // no, swap...
  3048. tmpTfxView = tfxInfo->tfxViews[i];
  3049. tfxInfo->tfxViews[i] = tfxInfo->tfxViews[j];
  3050. tfxInfo->tfxViews[i] = tmpTfxView;
  3051. }
  3052. }
  3053. SNMPDBG((
  3054. SNMP_LOG_VERBOSE,
  3055. "SNMP: TFX: Adding view [%d] %s.\n",
  3056. tfxInfo->tfxViews[i].mibView->viewOid.idLength,
  3057. SnmpUtilOidToA(&(tfxInfo->tfxViews[i].mibView->viewOid))
  3058. ));
  3059. }
  3060. } else {
  3061. // free structure
  3062. FreeTfxInfo(tfxInfo);
  3063. // reinitialize
  3064. tfxInfo = NULL;
  3065. }
  3066. return (LPVOID)tfxInfo;
  3067. }
  3068. SNMPAPI
  3069. SNMP_FUNC_TYPE
  3070. SnmpTfxQuery(
  3071. SnmpTfxHandle tfxHandle,
  3072. BYTE requestType,
  3073. RFC1157VarBindList * vbl,
  3074. AsnInteger * errorStatus,
  3075. AsnInteger * errorIndex
  3076. )
  3077. {
  3078. SnmpExtQueryList ql;
  3079. SnmpTfxInfo *tfxInfo = tfxHandle;
  3080. int i;
  3081. // initialize
  3082. ql.query = NULL;
  3083. ql.len = 0;
  3084. ql.action = requestType;
  3085. // disassemble varbinds
  3086. VarBindListToQueryList(
  3087. (SnmpTfxInfo*)tfxHandle,
  3088. vbl,
  3089. &ql,
  3090. errorStatus,
  3091. errorIndex
  3092. );
  3093. // process queries
  3094. ProcessQueryList(
  3095. (SnmpTfxInfo*)tfxHandle,
  3096. &ql,
  3097. vbl,
  3098. errorStatus,
  3099. errorIndex
  3100. );
  3101. // reassemble varbinds
  3102. QueryListToVarBindList(
  3103. (SnmpTfxInfo*)tfxHandle,
  3104. &ql,
  3105. vbl,
  3106. errorStatus,
  3107. errorIndex
  3108. );
  3109. return TRUE;
  3110. }
  3111. VOID
  3112. SNMP_FUNC_TYPE
  3113. SnmpTfxClose(
  3114. SnmpTfxHandle tfxHandle
  3115. )
  3116. {
  3117. // simply treat as info and release
  3118. FreeTfxInfo((SnmpTfxInfo *)tfxHandle);
  3119. }