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.

606 lines
16 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. /*---------------------------------------------------------
  13. Filename: session.cpp
  14. Written By: B.Rajeev
  15. ----------------------------------------------------------*/
  16. #include "precomp.h"
  17. #include "common.h"
  18. #include "sync.h"
  19. #include "dummy.h"
  20. #include "flow.h"
  21. #include "reg.h"
  22. #include "frame.h"
  23. #include "timer.h"
  24. #include "message.h"
  25. #include "tsent.h"
  26. #include "transp.h"
  27. #include "vblist.h"
  28. #include "sec.h"
  29. #include "pdu.h"
  30. #include "ssent.h"
  31. #include "idmap.h"
  32. #include "opreg.h"
  33. #include "session.h"
  34. #include "pseudo.h"
  35. #include "fs_reg.h"
  36. #include "ophelp.h"
  37. #include "op.h"
  38. #include <winsock.h>
  39. #include "trap.h"
  40. SnmpSession::SnmpSession (
  41. IN SnmpTransport &transportProtocol,
  42. IN SnmpSecurity &security,
  43. IN SnmpEncodeDecode &a_SnmpEncodeDecode ,
  44. IN const ULONG retryCount,
  45. IN const ULONG retryTimeout,
  46. IN const ULONG varbindsPerPdu,
  47. IN const ULONG flowControlWindow
  48. )
  49. {
  50. retry_count = retryCount;
  51. retry_timeout = retryTimeout;
  52. varbinds_per_pdu = varbindsPerPdu;
  53. flow_control_window = flowControlWindow;
  54. }
  55. #pragma warning (disable:4355)
  56. SnmpImpSession::SnmpImpSession (
  57. IN SnmpTransport &transportProtocol,
  58. IN SnmpSecurity &security,
  59. IN SnmpEncodeDecode &a_SnmpEncodeDecode ,
  60. IN const ULONG retryCount,
  61. IN const ULONG retryTimeout,
  62. IN const ULONG varbindsPerPdu,
  63. IN const ULONG flowControlWindow)
  64. : SnmpSession(transportProtocol, security, a_SnmpEncodeDecode,
  65. RetryCount(retryCount),
  66. RetryTimeout(retryTimeout),
  67. VarbindsPerPdu(varbindsPerPdu),
  68. WindowSize(flowControlWindow)),
  69. m_SessionWindow(*this),
  70. transport(transportProtocol),
  71. security(security),
  72. m_EncodeDecode(a_SnmpEncodeDecode) ,
  73. flow_control(*this, SnmpImpSession :: WindowSize ( GetFlowControlWindow() ) ),
  74. message_registry(*this),
  75. frame_registry(*this),
  76. timer(*this)
  77. {
  78. is_valid = FALSE;
  79. if ( !transport() || !security() || !m_SessionWindow() )
  80. return;
  81. received_session_frame_id = ILLEGAL_SESSION_FRAME_ID;
  82. destroy_self = FALSE;
  83. strobe_count = 1 ;
  84. // generate timer_event_id and register with the timer
  85. timer_event_id = timer.SetTimerEvent(MIN(100,retry_timeout/10));
  86. is_valid = TRUE;
  87. }
  88. #pragma warning (default:4355)
  89. ULONG SnmpImpSession::RetryCount(IN const ULONG retry_count)
  90. {
  91. return retry_count ;
  92. }
  93. ULONG SnmpImpSession::RetryTimeout(IN const ULONG retry_timeout)
  94. {
  95. return ( (retry_timeout==0)?
  96. DEF_RETRY_TIMEOUT: retry_timeout);
  97. }
  98. ULONG SnmpImpSession::VarbindsPerPdu(IN const ULONG varbinds_per_pdu)
  99. {
  100. return ( (varbinds_per_pdu==0)?
  101. DEF_VARBINDS_PER_PDU: varbinds_per_pdu);
  102. }
  103. ULONG SnmpImpSession::WindowSize(IN const ULONG window_size)
  104. {
  105. return ( (window_size==0)? DEF_WINDOW_SIZE: window_size);
  106. }
  107. void SnmpImpSession::RegisterOperation(IN SnmpOperation &operation)
  108. {
  109. CriticalSectionLock access_lock(session_CriticalSection);
  110. if ( !access_lock.GetLock(INFINITE) )
  111. return;
  112. operation_registry.Register(operation);
  113. // access_lock.UnLock(); The lock may be released at this point
  114. }
  115. // updates the number of operations currently registered
  116. // when the count goes to 0 and the destroy_self flag is set,
  117. // it posts the WinSnmpSession :: g_DeleteSessionEvent message.
  118. void SnmpImpSession::DeregisterOperation(IN SnmpOperation &operation)
  119. {
  120. CriticalSectionLock access_lock(session_CriticalSection);
  121. if ( !access_lock.GetLock(INFINITE) )
  122. return;
  123. operation_registry.Deregister(operation);
  124. if ( (destroy_self == TRUE) &&
  125. (operation_registry.GetNumRegistered() == 0) )
  126. m_SessionWindow.PostMessage(Window :: g_DeleteSessionEvent, 0, 0);
  127. // access_lock.UnLock(); The lock may be released at this point
  128. }
  129. // when the WinSnmpSession :: g_DeleteSessionEvent is received, the session deletes itself
  130. // no locks are obtained since our assumption is that no other objects would be
  131. // accessing the session at this time
  132. void SnmpImpSession::HandleDeletionEvent()
  133. {
  134. delete this;
  135. }
  136. // the session posts a message to destroy self if the number of registered
  137. // sessions is 0. otherwise the session is flagged for the same action when
  138. // the number of registered operations drops to 0.
  139. BOOL SnmpImpSession::DestroySession()
  140. {
  141. CriticalSectionLock access_lock(session_CriticalSection);
  142. if ( !access_lock.GetLock(INFINITE) )
  143. return FALSE;
  144. if ( operation_registry.GetNumRegistered() == 0 )
  145. {
  146. m_SessionWindow.PostMessage(Window :: g_DeleteSessionEvent, 0, 0);
  147. return TRUE;
  148. }
  149. else
  150. destroy_self = TRUE; // flag self for destruction
  151. access_lock.UnLock();
  152. return FALSE;
  153. }
  154. void SnmpImpSession::SessionSendFrame
  155. (
  156. IN SnmpOperation &operation,
  157. OUT SessionFrameId &session_frame_id,
  158. IN SnmpPdu &snmpPdu
  159. )
  160. {
  161. SessionSendFrame(operation, session_frame_id, snmpPdu, security);
  162. }
  163. void SnmpImpSession::SessionSendFrame
  164. (
  165. IN SnmpOperation &operation,
  166. OUT SessionFrameId &session_frame_id,
  167. IN SnmpPdu &snmpPdu,
  168. IN SnmpSecurity &snmp_security
  169. )
  170. {
  171. try
  172. {
  173. CriticalSectionLock access_lock(session_CriticalSection);
  174. if ( !access_lock.GetLock(INFINITE) )
  175. return;
  176. if ( !is_valid )
  177. return;
  178. session_frame_id = frame_registry.GenerateSessionFrameId();
  179. SnmpErrorReport error_report = snmp_security.Secure (
  180. m_EncodeDecode,
  181. snmpPdu
  182. );
  183. // if already errored, register the error report in the sent state
  184. if ( error_report.GetError() != Snmp_Success )
  185. {
  186. delete & snmpPdu;
  187. PostSentFrameEvent(
  188. session_frame_id,
  189. operation,
  190. SnmpErrorReport(Snmp_Error, Snmp_Local_Error)
  191. ) ;
  192. return;
  193. }
  194. Message *message = new Message(session_frame_id, snmpPdu, operation);
  195. DebugMacro4(
  196. SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
  197. __FILE__,__LINE__,
  198. L"new message(id%d,op%d)\n",session_frame_id, &(message->GetOperation())
  199. ) ;
  200. )
  201. flow_control.SendMessage(*message);
  202. }
  203. catch ( Heap_Exception e_He )
  204. {
  205. PostSentFrameEvent(
  206. session_frame_id,
  207. operation,
  208. SnmpErrorReport(Snmp_Error, Snmp_Local_Error)
  209. );
  210. return;
  211. }
  212. catch(GeneralException exception)
  213. {
  214. PostSentFrameEvent(
  215. session_frame_id,
  216. operation,
  217. SnmpErrorReport(exception.GetError(), exception.GetStatus())
  218. );
  219. return;
  220. }
  221. }
  222. void SnmpImpSession::PostSentFrameEvent (
  223. SessionFrameId session_frame_id ,
  224. SnmpOperation &operation,
  225. SnmpErrorReport errorReport
  226. )
  227. {
  228. try
  229. {
  230. store.Register (
  231. session_frame_id,
  232. operation,
  233. errorReport
  234. ) ;
  235. }
  236. catch ( Heap_Exception e_He )
  237. {
  238. }
  239. catch ( GeneralException exception )
  240. {
  241. }
  242. m_SessionWindow.PostMessage ( Window :: g_SentFrameEvent, session_frame_id, (LPARAM)&operation);
  243. }
  244. void SnmpImpSession::HandleSentFrame (
  245. IN SessionFrameId session_frame_id ,
  246. IN SnmpOperation *operation
  247. )
  248. {
  249. SnmpOperation *tmp_operation;
  250. SnmpErrorReport error_report = store.Remove(session_frame_id, tmp_operation);
  251. if ( tmp_operation == NULL )
  252. {
  253. DebugMacro4(
  254. SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
  255. __FILE__,__LINE__,
  256. L"HandleSentFrame could not locate sent message error in store(id%d,op%lx)\n",session_frame_id, operation
  257. ) ;
  258. )
  259. }
  260. // ignore it if no corresponding operation
  261. if ( operation == NULL )
  262. {
  263. DebugMacro4(
  264. SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
  265. __FILE__,__LINE__,
  266. L"HandleSentFrame received null operation(id%d)\n",session_frame_id
  267. ) ;
  268. )
  269. return;
  270. }
  271. operation->SentFrame(session_frame_id, error_report);
  272. }
  273. SnmpOperation *SnmpImpSession::GetOperation(IN const SessionFrameId session_frame_id)
  274. {
  275. WaitingMessage *waiting_message = frame_registry.GetWaitingMessage(session_frame_id);
  276. if (waiting_message == NULL)
  277. return NULL;
  278. return &(waiting_message->GetMessage()->GetOperation());
  279. }
  280. void SnmpImpSession::SessionSentFrame
  281. (
  282. IN TransportFrameId transport_frame_id,
  283. IN SnmpErrorReport &errorReport
  284. )
  285. {
  286. try
  287. {
  288. CriticalSectionLock access_lock(session_CriticalSection);
  289. if ( !access_lock.GetLock(INFINITE) )
  290. return;
  291. // obtain and remove the session frame id
  292. // obtain corresponding operation and inform it
  293. SessionFrameId session_frame_id = id_mapping.DisassociateTransportFrameId(transport_frame_id);
  294. // determine corresponding waiting message
  295. WaitingMessage *waiting_message = frame_registry.GetWaitingMessage(session_frame_id);
  296. // ignore if no such waiting message
  297. if (waiting_message == NULL)
  298. return;
  299. // if the error report shows an error during transport,
  300. // wrap up the waiting message and return
  301. if ( errorReport.GetError() != Snmp_Success )
  302. {
  303. waiting_message->WrapUp(SnmpErrorReport(errorReport));
  304. return;
  305. }
  306. // inform the waiting message of the sent message processing event
  307. waiting_message->SetSentMessageProcessed();
  308. // determine the corresponding operation
  309. SnmpOperation *operation = &(waiting_message->GetMessage()->GetOperation());
  310. access_lock.UnLock();
  311. // call to the operation is made outside the lock
  312. operation->SentFrame(session_frame_id, errorReport);
  313. // obtain the lock again to process the corresponding buffered
  314. // waiting message, if any
  315. if ( !access_lock.GetLock(INFINITE) )
  316. return;
  317. // if no such buffered snmp pdu, return
  318. if ( !waiting_message->ReplyBuffered() )
  319. return;
  320. SnmpPdu *snmp_pdu = waiting_message->GetBufferedReply();
  321. // set the state information for processing the buffered message
  322. received_session_frame_id = ILLEGAL_SESSION_FRAME_ID;
  323. // proceed with processing the snmp_pdu
  324. waiting_message->ReceiveReply(snmp_pdu);
  325. // save the information needed to notify the targeted operation
  326. // before releasing the lock
  327. SessionFrameId target_session_frame_id = received_session_frame_id;
  328. SnmpOperation *target_operation = operation_to_notify;
  329. access_lock.UnLock();
  330. // inform the target operation of the frame receipt
  331. if ( target_session_frame_id != ILLEGAL_SESSION_FRAME_ID )
  332. {
  333. target_operation->ReceiveFrame(target_session_frame_id, *snmp_pdu,
  334. SnmpErrorReport(Snmp_Success, Snmp_No_Error));
  335. }
  336. delete & snmp_pdu->GetVarbindList () ;
  337. delete snmp_pdu;
  338. }
  339. catch ( Heap_Exception e_He )
  340. {
  341. return;
  342. }
  343. catch(GeneralException exception)
  344. {
  345. return;
  346. }
  347. }
  348. void SnmpImpSession::SessionReceiveFrame (
  349. IN SnmpPdu &snmpPdu,
  350. IN SnmpErrorReport &errorReport
  351. )
  352. {
  353. try
  354. {
  355. CriticalSectionLock access_lock(session_CriticalSection);
  356. if ( !access_lock.GetLock(INFINITE) )
  357. return;
  358. // set the state information for processing the buffered message
  359. received_session_frame_id = ILLEGAL_SESSION_FRAME_ID;
  360. // proceed with processing the snmp_pdu
  361. message_registry.MessageArrivalNotification(snmpPdu);
  362. // save the information needed to notify the targeted operation
  363. // before releasing the lock
  364. SessionFrameId target_session_frame_id = received_session_frame_id;
  365. SnmpOperation *target_operation = operation_to_notify;
  366. access_lock.UnLock();
  367. // inform the target operation of the frame receipt
  368. if ( target_session_frame_id != ILLEGAL_SESSION_FRAME_ID )
  369. target_operation->ReceiveFrame(target_session_frame_id, snmpPdu,
  370. errorReport);
  371. }
  372. catch ( Heap_Exception e_He )
  373. {
  374. return ;
  375. }
  376. catch(GeneralException exception)
  377. {
  378. return;
  379. }
  380. }
  381. void SnmpImpSession::NotifyOperation (
  382. IN const SessionFrameId session_frame_id,
  383. IN const SnmpPdu &snmp_pdu,
  384. IN const SnmpErrorReport &error_report
  385. )
  386. {
  387. // determine the corresponding operation and
  388. // call its SessionReceiveFrame
  389. SnmpOperation *operation = GetOperation(session_frame_id);
  390. if ( error_report.GetError() != Snmp_Success )
  391. {
  392. PostSentFrameEvent(
  393. session_frame_id,
  394. *operation,
  395. error_report
  396. ) ;
  397. }
  398. else
  399. {
  400. received_session_frame_id = session_frame_id;
  401. operation_to_notify = operation;
  402. }
  403. }
  404. SnmpErrorReport SnmpImpSession::SessionCancelFrame (
  405. IN const SessionFrameId session_frame_id
  406. )
  407. {
  408. if ( !is_valid )
  409. return SnmpErrorReport(Snmp_Error, Snmp_Local_Error);
  410. try
  411. {
  412. CriticalSectionLock access_lock(session_CriticalSection);
  413. if ( !access_lock.GetLock(INFINITE) )
  414. return SnmpErrorReport(Snmp_Error, Snmp_Local_Error);
  415. frame_registry.CancelFrameNotification(session_frame_id);
  416. access_lock.UnLock();
  417. }
  418. catch ( Heap_Exception e_He )
  419. {
  420. return SnmpErrorReport(Snmp_Error, Snmp_Local_Error);
  421. }
  422. catch(GeneralException exception)
  423. {
  424. return exception;
  425. }
  426. // if we have reached this place, we must have succeeded
  427. return SnmpErrorReport(Snmp_Success, Snmp_No_Error);
  428. }
  429. SnmpImpSession::~SnmpImpSession(void)
  430. {
  431. // if required, cancels timer event
  432. if ( timer_event_id != ILLEGAL_TIMER_EVENT_ID )
  433. {
  434. timer.CancelTimer(timer_event_id);
  435. timer_event_id = ILLEGAL_TIMER_EVENT_ID;
  436. }
  437. }
  438. void * SnmpV1OverIp::operator()(void) const
  439. {
  440. if ( (SnmpUdpIpImp::operator()() == NULL) ||
  441. (SnmpV1EncodeDecode::operator()() == NULL) ||
  442. (SnmpCommunityBasedSecurity::operator()() == NULL) ||
  443. (SnmpImpSession::operator()() == NULL) )
  444. return NULL;
  445. else
  446. return (void *)this;
  447. }
  448. void * SnmpV1OverIpx::operator()(void) const
  449. {
  450. if ( (SnmpIpxImp::operator()() == NULL) ||
  451. (SnmpV1EncodeDecode::operator()() == NULL) ||
  452. (SnmpCommunityBasedSecurity::operator()() == NULL) ||
  453. (SnmpImpSession::operator()() == NULL) )
  454. return NULL;
  455. else
  456. return (void *)this;
  457. }
  458. void * SnmpV2COverIp::operator()(void) const
  459. {
  460. if ( (SnmpUdpIpImp::operator()() == NULL) ||
  461. (SnmpV2CEncodeDecode::operator()() == NULL) ||
  462. (SnmpCommunityBasedSecurity::operator()() == NULL) ||
  463. (SnmpImpSession::operator()() == NULL) )
  464. return NULL;
  465. else
  466. return (void *)this;
  467. }
  468. void * SnmpV2COverIpx::operator()(void) const
  469. {
  470. if ( (SnmpIpxImp::operator()() == NULL) ||
  471. (SnmpV2CEncodeDecode::operator()() == NULL) ||
  472. (SnmpCommunityBasedSecurity::operator()() == NULL) ||
  473. (SnmpImpSession::operator()() == NULL) )
  474. return NULL;
  475. else
  476. return (void *)this;
  477. }