Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

737 lines
20 KiB

  1. //***************************************************************************
  2. //
  3. // File:
  4. //
  5. // Module: MS SNMP Provider
  6. //
  7. // Purpose:
  8. //
  9. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include <provexpt.h>
  14. #include <typeinfo.h>
  15. #include <snmptempl.h>
  16. #include <snmpmt.h>
  17. #include <snmpcl.h>
  18. #include <snmpcont.h>
  19. #include <snmptype.h>
  20. #include <snmpauto.h>
  21. #if _MSC_VER >= 1100
  22. template<> UINT AFXAPI HashKey <SnmpObjectIdentifierType&> (SnmpObjectIdentifierType &key)
  23. #else
  24. UINT HashKey (SnmpObjectIdentifierType &key)
  25. #endif
  26. {
  27. SnmpObjectIdentifier *objectIdentifier = ( SnmpObjectIdentifier * ) key.GetValueEncoding () ;
  28. UCHAR *value = ( UCHAR * ) objectIdentifier->GetValue () ;
  29. ULONG length = objectIdentifier->GetValueLength () * sizeof ( ULONG ) ;
  30. #if 1
  31. ULONG t_Length = length >> 2 ;
  32. value += t_Length ;
  33. length = length - t_Length ;
  34. #endif
  35. UINT hash;
  36. if (length > 1)
  37. {
  38. USHORT even = 0;
  39. USHORT odd = 0;
  40. #if 0
  41. for (ULONG i = length >> 1; i--;)
  42. {
  43. even += *value++;
  44. odd += *value++;
  45. }
  46. if (length & 1)
  47. {
  48. even += *value;
  49. }
  50. #else
  51. for (ULONG i = length >> 2; i--;)
  52. {
  53. even += *value++;
  54. even += *value++;
  55. even += *value++;
  56. odd += *value++;
  57. }
  58. if (length & 1)
  59. {
  60. even += *value;
  61. }
  62. #endif
  63. hash = odd>>8;
  64. hash |= (odd & 0xff) << 8;
  65. hash ^= even;
  66. }
  67. else
  68. {
  69. hash = *value;
  70. }
  71. return hash ;
  72. }
  73. #if _MSC_VER >= 1100
  74. template<> BOOL AFXAPI CompareElements <SnmpObjectIdentifierType , SnmpObjectIdentifierType >(
  75. const SnmpObjectIdentifierType* pElement1,
  76. const SnmpObjectIdentifierType* pElement2
  77. )
  78. #else
  79. BOOL CompareElements (
  80. SnmpObjectIdentifierType* pElement1,
  81. SnmpObjectIdentifierType* pElement2
  82. )
  83. #endif
  84. {
  85. return *( ( SnmpObjectIdentifier * ) pElement1->GetValueEncoding () ) == *( ( SnmpObjectIdentifier * )pElement2->GetValueEncoding () ) ;
  86. }
  87. VarBindObject :: VarBindObject (
  88. const SnmpObjectIdentifier &replyArg ,
  89. const SnmpValue &valueArg
  90. ) : value ( NULL ) ,
  91. reply ( replyArg )
  92. {
  93. value = valueArg.Copy () ;
  94. }
  95. VarBindObject :: ~VarBindObject ()
  96. {
  97. delete value ;
  98. }
  99. SnmpObjectIdentifier &VarBindObject :: GetObjectIdentifier ()
  100. {
  101. return reply ;
  102. }
  103. SnmpValue &VarBindObject :: GetValue ()
  104. {
  105. return *value ;
  106. }
  107. VarBindQueue :: VarBindQueue ()
  108. {
  109. }
  110. VarBindQueue :: ~VarBindQueue ()
  111. {
  112. POSITION position = queue.GetHeadPosition () ;
  113. while ( position )
  114. {
  115. VarBindObject *varBindObject = queue.GetNext ( position ) ;
  116. delete varBindObject ;
  117. }
  118. queue.RemoveAll () ;
  119. }
  120. void VarBindQueue :: Add ( VarBindObject *varBindObject )
  121. {
  122. queue.AddTail ( varBindObject ) ;
  123. }
  124. VarBindObject *VarBindQueue :: Get ()
  125. {
  126. return queue.IsEmpty () ? NULL : queue.GetHead () ;
  127. }
  128. VarBindObject *VarBindQueue :: Delete ()
  129. {
  130. VarBindObject *object = NULL ;
  131. if ( ! queue.IsEmpty () )
  132. {
  133. object = queue.GetHead () ;
  134. queue.RemoveHead () ;
  135. }
  136. return object ;
  137. }
  138. VarBindObjectRequest :: VarBindObjectRequest (
  139. const SnmpObjectIdentifierType &varBindArg
  140. ) : varBind ( varBindArg ) , requested ( varBindArg ) , repeatRequest ( TRUE )
  141. {
  142. }
  143. VarBindObjectRequest :: VarBindObjectRequest (
  144. const SnmpObjectIdentifierType &varBindArg ,
  145. const SnmpObjectIdentifierType &requestedVarBindArg
  146. ) : varBind ( varBindArg ) , requested ( requestedVarBindArg ) , repeatRequest ( TRUE )
  147. {
  148. }
  149. VarBindObjectRequest :: VarBindObjectRequest () : repeatRequest ( TRUE )
  150. {
  151. }
  152. VarBindObjectRequest :: ~VarBindObjectRequest ()
  153. {
  154. }
  155. const SnmpObjectIdentifierType &VarBindObjectRequest :: GetRequested () const
  156. {
  157. return requested ;
  158. }
  159. const SnmpObjectIdentifierType &VarBindObjectRequest :: GetVarBind () const
  160. {
  161. return varBind ;
  162. }
  163. void VarBindObjectRequest :: SetRequested ( const SnmpObjectIdentifierType &requestedArg )
  164. {
  165. requested = requestedArg ;
  166. }
  167. void VarBindObjectRequest :: SetVarBind ( const SnmpObjectIdentifierType &varBindArg )
  168. {
  169. varBind = varBindArg ;
  170. }
  171. void VarBindObjectRequest :: AddQueuedObject ( VarBindObject *object )
  172. {
  173. varBindResponseQueue.Add ( object ) ;
  174. }
  175. VarBindObject *VarBindObjectRequest :: GetQueuedObject ()
  176. {
  177. return varBindResponseQueue.Get () ;
  178. }
  179. VarBindObject *VarBindObjectRequest :: DeleteQueueudObject ()
  180. {
  181. return varBindResponseQueue.Delete () ;
  182. }
  183. GetNextOperation :: GetNextOperation (
  184. IN SnmpSession &session ,
  185. SnmpAutoRetrieveOperation &autoRetrieveOperation
  186. ) : SnmpGetNextOperation ( session ) ,
  187. operation ( NULL ) ,
  188. minimumInstance ( NULL , 0 ) ,
  189. cancelledRequest ( FALSE ) ,
  190. m_RequestContainerLength ( 0 ) ,
  191. m_RequestContainer ( NULL ) ,
  192. m_RequestIndexContainer ( NULL )
  193. {
  194. operation = &autoRetrieveOperation ;
  195. }
  196. GetNextOperation :: ~GetNextOperation ()
  197. {
  198. Cleanup () ;
  199. delete [] m_RequestContainer ;
  200. delete [] m_RequestIndexContainer ;
  201. delete operation ;
  202. }
  203. void GetNextOperation :: Cleanup ()
  204. {
  205. if ( m_RequestContainer )
  206. {
  207. for ( ULONG t_Index = 0 ; t_Index < m_RequestContainerLength ; t_Index ++ )
  208. {
  209. VarBindObjectRequest *varBindObjectRequest = m_RequestContainer [ t_Index ] ;
  210. m_RequestContainer [ t_Index ] = NULL ;
  211. delete varBindObjectRequest ;
  212. }
  213. }
  214. }
  215. void GetNextOperation :: SendRequest (
  216. SnmpVarBindList &varBindList
  217. )
  218. {
  219. cancelledRequest = FALSE ;
  220. ULONG t_Count = varBindList.GetLength () ;
  221. m_RequestContainerLength = t_Count ;
  222. m_RequestContainer = new VarBindObjectRequest * [ t_Count ] ;
  223. m_RequestIndexContainer = new ULONG [ t_Count ] ;
  224. ZeroMemory ( m_RequestContainer , sizeof ( VarBindObjectRequest * ) * t_Count ) ;
  225. ZeroMemory ( m_RequestIndexContainer , sizeof ( ULONG ) * t_Count ) ;
  226. ULONG t_Index = 0 ;
  227. varBindList.Reset () ;
  228. while ( varBindList.Next () )
  229. {
  230. const SnmpVarBind *varBind = varBindList.Get () ;
  231. SnmpObjectIdentifierType requestObject ( varBind->GetInstance () ) ;
  232. VarBindObjectRequest *request = new VarBindObjectRequest ( requestObject ) ;
  233. m_RequestContainer [ t_Index ] = request ;
  234. t_Index ++ ;
  235. }
  236. Send () ;
  237. }
  238. void GetNextOperation :: SendRequest (
  239. SnmpVarBindList &varBindList ,
  240. SnmpVarBindList &startVarBindList
  241. )
  242. {
  243. cancelledRequest = FALSE ;
  244. ULONG t_Count = varBindList.GetLength () ;
  245. m_RequestContainerLength = t_Count ;
  246. m_RequestContainer = new VarBindObjectRequest * [ t_Count ] ;
  247. m_RequestIndexContainer = new ULONG [ t_Count ] ;
  248. ULONG t_Index = 0 ;
  249. varBindList.Reset () ;
  250. startVarBindList.Reset () ;
  251. while ( startVarBindList.Next () && varBindList.Next () )
  252. {
  253. const SnmpVarBind *varBind = varBindList.Get () ;
  254. const SnmpVarBind *startVarBind = startVarBindList.Get () ;
  255. SnmpObjectIdentifierType requestObject ( varBind->GetInstance () ) ;
  256. SnmpObjectIdentifierType startRequestObject ( startVarBind->GetInstance () ) ;
  257. VarBindObjectRequest *request = new VarBindObjectRequest ( requestObject , startRequestObject ) ;
  258. m_RequestContainer [ t_Index ] = request ;
  259. t_Index ++ ;
  260. }
  261. Send () ;
  262. }
  263. void GetNextOperation :: DestroyOperation ()
  264. {
  265. SnmpGetNextOperation :: DestroyOperation () ;
  266. }
  267. void GetNextOperation :: CancelRequest ()
  268. {
  269. cancelledRequest = TRUE ;
  270. SnmpGetNextOperation :: CancelRequest () ;
  271. }
  272. void GetNextOperation :: Send ()
  273. {
  274. BOOL t_Count = 0 ;
  275. SnmpVarBindList sendVarBindList ;
  276. for ( ULONG t_Index = 0 ; t_Index < m_RequestContainerLength ; t_Index ++ )
  277. {
  278. SnmpObjectIdentifierType objectIdentifierType ;
  279. VarBindObjectRequest *varBindObjectRequest = m_RequestContainer [ t_Index ] ;
  280. if ( varBindObjectRequest->GetRepeatRequest () )
  281. {
  282. SnmpNull snmpNull ;
  283. SnmpVarBind varBind (
  284. * ( SnmpObjectIdentifier * ) varBindObjectRequest->GetRequested ().GetValueEncoding () ,
  285. snmpNull
  286. ) ;
  287. sendVarBindList.Add ( varBind ) ;
  288. m_RequestIndexContainer [ t_Count ] = t_Index ;
  289. t_Count ++ ;
  290. }
  291. }
  292. SnmpGetNextOperation :: SendRequest ( sendVarBindList ) ;
  293. }
  294. void GetNextOperation :: SentFrame (
  295. IN const SessionFrameId session_frame_id ,
  296. const SnmpErrorReport &errorReport
  297. )
  298. {
  299. switch ( errorReport.GetError () )
  300. {
  301. case Snmp_Success:
  302. {
  303. }
  304. break ;
  305. default:
  306. {
  307. }
  308. break ;
  309. }
  310. operation->SentFrame ( session_frame_id , errorReport ) ;
  311. SnmpGetNextOperation :: SentFrame ( session_frame_id , errorReport ) ;
  312. }
  313. void GetNextOperation :: ReceiveResponse ()
  314. {
  315. BOOL receiveComplete = TRUE ;
  316. for ( ULONG t_Index = 0 ; t_Index < m_RequestContainerLength ; t_Index ++ )
  317. {
  318. VarBindObjectRequest *varBindObjectRequest = m_RequestContainer [ t_Index ] ;
  319. if ( varBindObjectRequest->GetRepeatRequest () )
  320. {
  321. receiveComplete = FALSE ;
  322. }
  323. }
  324. if ( ! cancelledRequest )
  325. {
  326. // Check to see if we have finished
  327. if ( ! receiveComplete )
  328. {
  329. // Request next response
  330. Send () ;
  331. }
  332. // Process received information
  333. while ( ProcessRow () ) ;
  334. }
  335. if ( receiveComplete )
  336. {
  337. // We've finished
  338. operation->ReceiveResponse () ;
  339. // Clear all resources
  340. Cleanup () ;
  341. }
  342. }
  343. BOOL GetNextOperation :: ProcessRow ()
  344. {
  345. // Process Row information
  346. BOOL initialised = FALSE ;
  347. BOOL objectHasNoValueAndIsRepeating = FALSE ;
  348. SnmpObjectIdentifier objectIdentifier ( NULL , 0 ) ;
  349. SnmpObjectIdentifier suffix ( NULL , 0 ) ;
  350. // Determine minimum instance
  351. for ( ULONG t_Index = 0 ; t_Index < m_RequestContainerLength ; t_Index ++ )
  352. {
  353. VarBindObjectRequest *varBindObjectRequest = m_RequestContainer [ t_Index ] ;
  354. VarBindObject *queuedObject = varBindObjectRequest->GetQueuedObject () ;
  355. if ( queuedObject )
  356. {
  357. // Get row information associated with table property, i.e. instance of initial varbind requested.
  358. SnmpObjectIdentifierType varBindType = varBindObjectRequest->GetVarBind () ;
  359. SnmpObjectIdentifier *varBind = ( SnmpObjectIdentifier * ) varBindType.GetValueEncoding () ;
  360. if(varBind)
  361. {
  362. BOOL t_Status = queuedObject->GetObjectIdentifier ().Suffix ( varBind->GetValueLength () , suffix ) ;
  363. if ( t_Status )
  364. {
  365. if ( initialised )
  366. {
  367. if ( suffix < objectIdentifier )
  368. {
  369. // Least instance so far
  370. objectIdentifier = suffix ;
  371. }
  372. else
  373. {
  374. // Greater Than
  375. }
  376. }
  377. else
  378. {
  379. // objectIdentifier hasn't been set to a legal instance yet.
  380. objectIdentifier = suffix ;
  381. initialised = TRUE ;
  382. }
  383. }
  384. else
  385. {
  386. // No more rows as yet
  387. }
  388. }
  389. }
  390. else
  391. {
  392. if ( varBindObjectRequest->GetRepeatRequest () )
  393. {
  394. objectHasNoValueAndIsRepeating = TRUE ;
  395. }
  396. }
  397. }
  398. if ( initialised && ( ! objectHasNoValueAndIsRepeating ) )
  399. {
  400. minimumInstance = objectIdentifier ;
  401. // Process all columns which contain row of least minimum
  402. for ( ULONG t_Index = 0 ; t_Index < m_RequestContainerLength ; t_Index ++ )
  403. {
  404. VarBindObjectRequest *varBindObjectRequest = m_RequestContainer [ t_Index ] ;
  405. VarBindObject *queuedObject = varBindObjectRequest->GetQueuedObject () ;
  406. if ( queuedObject )
  407. {
  408. SnmpObjectIdentifierType varBindType = varBindObjectRequest->GetVarBind () ;
  409. SnmpObjectIdentifier *varBind = ( SnmpObjectIdentifier * ) varBindType.GetValueEncoding () ;
  410. if ( varBind && queuedObject->GetObjectIdentifier ().Suffix ( varBind->GetValueLength () , suffix ) )
  411. {
  412. if ( suffix == minimumInstance )
  413. {
  414. // Row to be processed
  415. SnmpNull snmpNull ;
  416. SnmpErrorReport errorReport ( Snmp_Success , Snmp_No_Error ) ;
  417. SnmpVarBind requestVarBind ( *varBind , snmpNull ) ;
  418. SnmpVarBind replyVarBind ( minimumInstance , queuedObject->GetValue () ) ;
  419. operation->ReceiveRowVarBindResponse ( t_Index + 1 , requestVarBind , replyVarBind , errorReport ) ;
  420. // Check CancelRequest hasn't been called in callback
  421. if ( cancelledRequest )
  422. {
  423. return FALSE ;
  424. }
  425. // Remove row
  426. VarBindObject *queuedObject = varBindObjectRequest->DeleteQueueudObject () ;
  427. delete queuedObject ;
  428. }
  429. else
  430. {
  431. // Row is lexicographically greater than process row
  432. }
  433. }
  434. else
  435. {
  436. // Problem Here
  437. }
  438. }
  439. }
  440. // Forward call to AutoRetrieveOperation
  441. operation->ReceiveRowResponse () ;
  442. }
  443. else
  444. {
  445. // Zero rows to process
  446. }
  447. return initialised && ( ! objectHasNoValueAndIsRepeating ) ;
  448. }
  449. void GetNextOperation :: ReceiveVarBindResponse (
  450. IN const ULONG &var_bind_index,
  451. IN const SnmpVarBind &requestVarBind ,
  452. IN const SnmpVarBind &replyVarBind ,
  453. IN const SnmpErrorReport &error
  454. )
  455. {
  456. ULONG t_Index = m_RequestIndexContainer [ var_bind_index - 1 ] ;
  457. VarBindObjectRequest *varBindObjectRequest = m_RequestContainer [ t_Index ] ;
  458. /*
  459. * check for v2c errored responses
  460. */
  461. if ( typeid ( replyVarBind.GetValue () ) == typeid ( SnmpEndOfMibView ) )
  462. {
  463. // Stop further requests for this column
  464. varBindObjectRequest->SetRepeatRequest ( FALSE ) ;
  465. }
  466. else
  467. {
  468. // Locate request object
  469. // Check we haven't gone backwards lexicographically, which would result in an infinitely repeating request.
  470. if ( replyVarBind.GetInstance () > requestVarBind.GetInstance () )
  471. {
  472. // Check we haven't reached end of table
  473. SnmpObjectIdentifier *objectIdentifier = ( SnmpObjectIdentifier *) varBindObjectRequest->GetVarBind ().GetValueEncoding () ;
  474. if ( objectIdentifier && replyVarBind.GetInstance().Equivalent ( *objectIdentifier , objectIdentifier->GetValueLength () ) )
  475. {
  476. // Add row information to column of table
  477. SnmpObjectIdentifier snmpObjectIdentifier ( 0 , NULL ) ;
  478. SnmpObjectIdentifier suffix ( 0 , NULL ) ;
  479. SnmpNull snmpNull ;
  480. BOOL t_Status = replyVarBind.GetInstance().Suffix ( objectIdentifier->GetValueLength () , suffix ) ;
  481. if ( t_Status )
  482. {
  483. SnmpVarBind sendVarBind ( snmpObjectIdentifier , snmpNull ) ;
  484. SnmpVarBind adjustedReplyVarBind ( suffix , replyVarBind.GetValue () ) ;
  485. LONG t_Option = operation->EvaluateNextRequest (
  486. var_bind_index,
  487. requestVarBind ,
  488. adjustedReplyVarBind ,
  489. sendVarBind
  490. ) ;
  491. if ( t_Option == 0 )
  492. {
  493. VarBindObject *varBindObject = new VarBindObject ( replyVarBind.GetInstance () , replyVarBind.GetValue () ) ;
  494. varBindObjectRequest->AddQueuedObject ( varBindObject ) ;
  495. // Update map to identify request next time around
  496. SnmpObjectIdentifierType replyObject ( replyVarBind.GetInstance () ) ;
  497. varBindObjectRequest->SetRequested ( replyObject ) ;
  498. }
  499. else if ( t_Option > 0 )
  500. {
  501. VarBindObject *varBindObject = new VarBindObject ( replyVarBind.GetInstance () , replyVarBind.GetValue () ) ;
  502. varBindObjectRequest->AddQueuedObject ( varBindObject ) ;
  503. // Update map to identify request next time around
  504. SnmpObjectIdentifierType replyObject ( *objectIdentifier + sendVarBind.GetInstance () ) ;
  505. varBindObjectRequest->SetRequested ( replyObject ) ;
  506. }
  507. else
  508. {
  509. VarBindObject *varBindObject = new VarBindObject ( replyVarBind.GetInstance () , replyVarBind.GetValue () ) ;
  510. varBindObjectRequest->AddQueuedObject ( varBindObject ) ;
  511. varBindObjectRequest->SetRepeatRequest ( FALSE ) ;
  512. }
  513. }
  514. else
  515. {
  516. varBindObjectRequest->SetRepeatRequest ( FALSE ) ;
  517. }
  518. }
  519. else
  520. {
  521. // instance received is not row of column, i.e End Of Table
  522. varBindObjectRequest->SetRepeatRequest ( FALSE ) ;
  523. }
  524. }
  525. else
  526. {
  527. // instance requested is greater than instance replied
  528. varBindObjectRequest->SetRepeatRequest ( FALSE ) ;
  529. }
  530. }
  531. operation->ReceiveVarBindResponse ( var_bind_index,requestVarBind , replyVarBind , error ) ;
  532. }
  533. void GetNextOperation :: ReceiveErroredVarBindResponse(
  534. IN const ULONG &var_bind_index,
  535. IN const SnmpVarBind &requestVarBind ,
  536. IN const SnmpErrorReport &error
  537. )
  538. {
  539. ULONG t_Index = m_RequestIndexContainer [ var_bind_index - 1 ] ;
  540. VarBindObjectRequest *varBindObjectRequest = m_RequestContainer [ t_Index ] ;
  541. switch ( error.GetError () )
  542. {
  543. case Snmp_Success:
  544. {
  545. /*
  546. * Can't happen
  547. */
  548. }
  549. break ;
  550. default:
  551. {
  552. // Stop further requests for this column
  553. varBindObjectRequest->SetRepeatRequest ( FALSE ) ;
  554. }
  555. break ;
  556. }
  557. operation->ReceiveErroredVarBindResponse ( var_bind_index , requestVarBind , error ) ;
  558. }
  559. void GetNextOperation :: FrameTooBig ()
  560. {
  561. operation->FrameTooBig () ;
  562. }
  563. void GetNextOperation :: FrameOverRun ()
  564. {
  565. operation->FrameTooBig () ;
  566. }
  567. SnmpAutoRetrieveOperation :: SnmpAutoRetrieveOperation (IN SnmpSession &session)
  568. {
  569. operation = new GetNextOperation ( session , *this ) ;
  570. }
  571. SnmpAutoRetrieveOperation :: ~SnmpAutoRetrieveOperation ()
  572. {
  573. }
  574. void SnmpAutoRetrieveOperation :: DestroyOperation ()
  575. {
  576. operation->DestroyOperation () ;
  577. }
  578. void SnmpAutoRetrieveOperation :: CancelRequest ()
  579. {
  580. operation->CancelRequest () ;
  581. }
  582. void SnmpAutoRetrieveOperation :: SendRequest ( SnmpVarBindList &varBindList )
  583. {
  584. operation->SendRequest ( varBindList ) ;
  585. }
  586. void SnmpAutoRetrieveOperation :: SendRequest ( SnmpVarBindList &varBindList , SnmpVarBindList &startVarBindList )
  587. {
  588. operation->SendRequest ( varBindList , startVarBindList ) ;
  589. }