Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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