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.

665 lines
19 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: ophelp.cpp
  14. Written By: B.Rajeev
  15. ----------------------------------------------------------*/
  16. #include "precomp.h"
  17. #include "common.h"
  18. #include "sync.h"
  19. #include "value.h"
  20. #include "encdec.h"
  21. #include "vblist.h"
  22. #include "sec.h"
  23. #include "pdu.h"
  24. #include "vbl.h"
  25. #include "fs_reg.h"
  26. #include "pseudo.h"
  27. #include "encap.h"
  28. #include "error.h"
  29. #include "ophelp.h"
  30. #include "dummy.h"
  31. #include "flow.h"
  32. #include "frame.h"
  33. #include "timer.h"
  34. #include "message.h"
  35. #include "ssent.h"
  36. #include "idmap.h"
  37. #include "opreg.h"
  38. #include "session.h"
  39. #include "op.h"
  40. #include <winsock.h>
  41. // returns an SnmpTransportAddress created using the HSNMP_ENTITY
  42. // this method returns the first transport address it can create
  43. // using the string form of the HSNMP_ENTITY supplied
  44. SnmpTransportAddress *OperationHelper::GetTransportAddress(IN HSNMP_ENTITY &haddr)
  45. {
  46. char buff[MAX_ADDRESS_LEN];
  47. SNMPAPI_STATUS status = SnmpEntityToStr(haddr, MAX_ADDRESS_LEN, (LPSTR)buff);
  48. if (SNMPAPI_FAILURE == status)
  49. {
  50. return (SnmpTransportAddress *)NULL;
  51. }
  52. //first try ip...
  53. SnmpTransportIpAddress *retip = new SnmpTransportIpAddress(buff, SNMP_ADDRESS_RESOLVE_VALUE);
  54. if (retip->IsValid())
  55. {
  56. return (SnmpTransportAddress *)retip;
  57. }
  58. delete retip;
  59. //next try ipx...
  60. SnmpTransportIpxAddress *retipx = new SnmpTransportIpxAddress(buff);
  61. if (retipx->IsValid())
  62. {
  63. return (SnmpTransportAddress *)retipx;
  64. }
  65. delete retipx;
  66. //nothing worked...
  67. return (SnmpTransportAddress *)NULL;
  68. }
  69. // returns an SnmpSecurity created using the HSNMP_CONTEXT
  70. // this method returns the first security context it can create
  71. // using the string form of the HSNMP_CONTEXT supplied
  72. SnmpSecurity *OperationHelper::GetSecurityContext(IN HSNMP_CONTEXT &hctxt)
  73. {
  74. smiOCTETS buff;
  75. SNMPAPI_STATUS status = SnmpContextToStr(hctxt, &buff);
  76. if (SNMPAPI_FAILURE == status)
  77. {
  78. return (SnmpSecurity *)NULL;
  79. }
  80. SnmpOctetString octstr( (UCHAR *)(buff.ptr), (ULONG)(buff.len) );
  81. SnmpCommunityBasedSecurity* retval = new SnmpCommunityBasedSecurity(octstr);
  82. SnmpFreeDescriptor (SNMP_SYNTAX_OCTETS, &buff);
  83. if (NULL != (*retval)())
  84. {
  85. return (SnmpSecurity *)retval;
  86. }
  87. delete retval;
  88. return (SnmpSecurity *)NULL;
  89. }
  90. // returns an SnmpVarBind containing an SnmpObjectIdentifier and an
  91. // SnmpValue created using the instance(OID) and the value(VALUE)
  92. SnmpVarBind *OperationHelper::GetVarBind(IN smiOID &instance,
  93. IN smiVALUE &value)
  94. {
  95. SnmpVarBind *var_bind = NULL ;
  96. // create an SnmpObjectIdentifier using the instance value
  97. SnmpObjectIdentifier id(instance.ptr, instance.len);
  98. // for each possible value for value.syntax, create the
  99. // corresponding SnmpValue
  100. switch(value.syntax)
  101. {
  102. case SNMP_SYNTAX_NULL: // null value
  103. {
  104. var_bind = new SnmpVarBind(id, SnmpNull () );
  105. }
  106. break;
  107. case SNMP_SYNTAX_INT: // integer *(has same value as SNMP_SYNTAX_INT32)*
  108. {
  109. var_bind = new SnmpVarBind(id, SnmpInteger(value.value.sNumber) ) ;
  110. }
  111. break;
  112. case SNMP_SYNTAX_UINT32: // integer *(has same value as SNMP_SYNTAX_GAUGE)*
  113. {
  114. var_bind = new SnmpVarBind(id, SnmpUInteger32(value.value.uNumber) ) ;
  115. }
  116. break;
  117. case SNMP_SYNTAX_CNTR32: // counter32
  118. {
  119. var_bind = new SnmpVarBind(id, SnmpCounter (value.value.uNumber) ) ;
  120. }
  121. break;
  122. case SNMP_SYNTAX_GAUGE32: // gauge
  123. {
  124. var_bind = new SnmpVarBind(id, SnmpGauge(value.value.uNumber) );
  125. }
  126. break;
  127. case SNMP_SYNTAX_TIMETICKS: // time ticks
  128. {
  129. var_bind = new SnmpVarBind(id, SnmpTimeTicks(value.value.uNumber) );
  130. }
  131. break;
  132. case SNMP_SYNTAX_OCTETS: // octets
  133. {
  134. var_bind = new SnmpVarBind(id, SnmpOctetString(value.value.string.ptr,
  135. value.value.string.len) ) ;
  136. }
  137. break;
  138. case SNMP_SYNTAX_OPAQUE: // opaque value
  139. {
  140. var_bind = new SnmpVarBind(id, SnmpOpaque(value.value.string.ptr,
  141. value.value.string.len) );
  142. }
  143. break;
  144. case SNMP_SYNTAX_OID: // object identifier
  145. {
  146. var_bind = new SnmpVarBind(id, SnmpObjectIdentifier(value.value.oid.ptr,
  147. value.value.oid.len) );
  148. }
  149. break;
  150. case SNMP_SYNTAX_IPADDR: // ip address value
  151. {
  152. if ( value.value.string.ptr )
  153. {
  154. var_bind = new SnmpVarBind(id, SnmpIpAddress(ntohl(*((ULONG *)value.value.string.ptr))) );
  155. }
  156. else
  157. {
  158. DebugMacro4(
  159. SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
  160. __FILE__,__LINE__,
  161. L"OperationHelper::DecodeVarBind: Invalid encoding\n"
  162. ) ;
  163. )
  164. var_bind = NULL ;
  165. }
  166. }
  167. break;
  168. case SNMP_SYNTAX_CNTR64: // counter64
  169. {
  170. var_bind = new SnmpVarBind(id, SnmpCounter64 (value.value.hNumber.lopart , value.value.hNumber.hipart ) );
  171. }
  172. break;
  173. case SNMP_SYNTAX_NOSUCHOBJECT:
  174. {
  175. var_bind = new SnmpVarBind(id, SnmpNoSuchObject () ) ;
  176. }
  177. break ;
  178. case SNMP_SYNTAX_NOSUCHINSTANCE:
  179. {
  180. var_bind = new SnmpVarBind(id, SnmpNoSuchInstance () ) ;
  181. }
  182. break ;
  183. case SNMP_SYNTAX_ENDOFMIBVIEW:
  184. {
  185. var_bind = new SnmpVarBind(id, SnmpEndOfMibView () ) ;
  186. }
  187. break ;
  188. default:
  189. {
  190. // it must be an unsupported type
  191. // return an SnmpNullValue by default
  192. var_bind = new SnmpVarBind(id, SnmpNull() );
  193. }
  194. break;
  195. };
  196. return var_bind;
  197. }
  198. void OperationHelper::TransmitFrame (
  199. OUT SessionFrameId &session_frame_id,
  200. VBList &vbl)
  201. {
  202. SnmpSecurity *security = operation.frame_state_registry.GetSecurity();
  203. // encode a frame
  204. SnmpPdu *t_SnmpPdu = new SnmpPdu ;
  205. SnmpErrorReport t_SnmpErrorReport ;
  206. SnmpTransportAddress *t_SrcTransportAddress = NULL ;
  207. SnmpTransportAddress *t_DstTransportAddress = NULL ;
  208. SnmpCommunityBasedSecurity *t_SnmpcommunityBasedSecurity = NULL ;
  209. try
  210. {
  211. operation.session.GetSnmpEncodeDecode ().EncodeFrame (
  212. *t_SnmpPdu ,
  213. session_frame_id ,
  214. operation.GetPduType () ,
  215. t_SnmpErrorReport ,
  216. vbl.GetVarBindList () ,
  217. t_SnmpcommunityBasedSecurity ,
  218. t_SrcTransportAddress ,
  219. t_DstTransportAddress
  220. );
  221. }
  222. catch ( Heap_Exception e_He )
  223. {
  224. delete t_SnmpPdu ;
  225. operation.m_OperationWindow.PostMessage (
  226. Window :: g_SendErrorEvent ,
  227. (WPARAM)&vbl,
  228. (LPARAM)(new GeneralException(Snmp_Error, Snmp_Local_Error,__FILE__,__LINE__))
  229. );
  230. return ;
  231. }
  232. catch ( GeneralException exception )
  233. {
  234. delete t_SnmpPdu ;
  235. operation.m_OperationWindow.PostMessage (
  236. Window :: g_SendErrorEvent ,
  237. (WPARAM)&vbl,
  238. (LPARAM)(new GeneralException(exception))
  239. );
  240. return ;
  241. }
  242. if ( security != NULL )
  243. {
  244. operation.session.SessionSendFrame (
  245. operation,
  246. session_frame_id,
  247. *t_SnmpPdu,
  248. *security
  249. );
  250. }
  251. else
  252. {
  253. operation.session.SessionSendFrame (
  254. operation,
  255. session_frame_id,
  256. *t_SnmpPdu
  257. );
  258. }
  259. }
  260. void OperationHelper::ReceiveResponse (
  261. ULONG var_index ,
  262. SnmpVarBindList &sent_var_bind_list,
  263. SnmpVarBindList &received_var_bind_list,
  264. SnmpErrorReport &error_report
  265. )
  266. {
  267. // check if the var bind list has the same length
  268. if ( sent_var_bind_list.GetLength() != received_var_bind_list.GetLength () )
  269. {
  270. operation.is_valid = FALSE;
  271. return;
  272. }
  273. sent_var_bind_list.Reset();
  274. received_var_bind_list.Reset();
  275. ULONG t_Index = 0 ;
  276. while( sent_var_bind_list.Next() && received_var_bind_list.Next() )
  277. {
  278. const SnmpVarBind *sent_var_bind = sent_var_bind_list.Get();
  279. const SnmpVarBind *received_var_bind = received_var_bind_list.Get();
  280. operation.ReceiveVarBindResponse(
  281. var_index + t_Index ,
  282. *sent_var_bind,
  283. *received_var_bind,
  284. error_report
  285. );
  286. t_Index ++ ;
  287. }
  288. }
  289. // processes the response (successful or otherwise) for the specified
  290. // frame. the frame may be retransmitted in case of a reply bearing
  291. // an errored index
  292. void OperationHelper::ProcessResponse (
  293. FrameState *frame_state,
  294. SnmpVarBindList &a_SnmpVarBindList ,
  295. SnmpErrorReport &a_SnmpErrorReport
  296. )
  297. {
  298. DebugMacro4(
  299. SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
  300. __FILE__,__LINE__,
  301. L"OperationHelper::ProcessResponse: eindex(%d), error(%d), status(%d)\n",a_SnmpErrorReport.GetIndex(), a_SnmpErrorReport.GetError(), a_SnmpErrorReport.GetStatus()
  302. ) ;
  303. )
  304. // if there is an error in a particular var bind
  305. if ( (a_SnmpErrorReport.GetIndex () != 0) && (a_SnmpErrorReport.GetStatus () != SNMP_ERROR_NOERROR) )
  306. {
  307. if ( operation.GetPduType () != SnmpEncodeDecode :: PduType :: SET )
  308. {
  309. // delete the corresponding var bind from the VBList
  310. // in the frame_state and announce the receipt of
  311. // errored var bind by making a callback
  312. VBList *vblist = frame_state->GetVBList();
  313. SnmpVarBind *errored_vb;
  314. try
  315. {
  316. errored_vb = vblist->Get(a_SnmpErrorReport.GetIndex () );
  317. }
  318. catch ( Heap_Exception e_He )
  319. {
  320. operation.ReceiveErroredResponse(
  321. frame_state->GetVBList()->GetIndex () ,
  322. frame_state->GetVBList()->GetVarBindList(),
  323. GeneralException(Snmp_Error, Snmp_Local_Error,__FILE__,__LINE__)
  324. );
  325. delete &frame_state;
  326. return;
  327. }
  328. catch(GeneralException exception)
  329. {
  330. operation.ReceiveErroredResponse(
  331. frame_state->GetVBList()->GetIndex () ,
  332. frame_state->GetVBList()->GetVarBindList(),
  333. exception
  334. );
  335. delete &frame_state;
  336. return;
  337. }
  338. // *** (SnmpStatus) casting
  339. SnmpErrorReport report(Snmp_Error, a_SnmpErrorReport.GetStatus () , a_SnmpErrorReport.GetIndex () );
  340. operation.ReceiveErroredVarBindResponse(
  341. vblist->GetIndex () + a_SnmpErrorReport.GetIndex () - 1 ,
  342. *errored_vb,
  343. report
  344. );
  345. delete errored_vb;
  346. try
  347. {
  348. vblist->Remove (a_SnmpErrorReport.GetIndex () );
  349. }
  350. catch ( Heap_Exception e_He )
  351. {
  352. operation.ReceiveErroredResponse(
  353. frame_state->GetVBList()->GetIndex () ,
  354. frame_state->GetVBList()->GetVarBindList(),
  355. GeneralException(Snmp_Error, Snmp_Local_Error,__FILE__,__LINE__)
  356. );
  357. delete &frame_state;
  358. return;
  359. }
  360. catch(GeneralException exception)
  361. {
  362. operation.ReceiveErroredResponse(
  363. frame_state->GetVBList()->GetIndex () ,
  364. frame_state->GetVBList()->GetVarBindList(),
  365. exception
  366. );
  367. delete &frame_state;
  368. return;
  369. }
  370. // if the VarBindList becomes empty, corresp. frame state
  371. // may be deleted
  372. if ( vblist->GetVarBindList().Empty() )
  373. delete frame_state;
  374. else
  375. {
  376. // Split the frame in half
  377. SnmpVarBindList &vbl = vblist->GetVarBindList ();
  378. if ( a_SnmpErrorReport.GetIndex () > 1 )
  379. {
  380. SnmpVarBindList *t_Car = vbl.Car ( a_SnmpErrorReport.GetIndex () - 1 ) ;
  381. VBList *t_List = new VBList (
  382. operation.session.GetSnmpEncodeDecode () ,
  383. *t_Car,
  384. vblist->GetIndex ()
  385. ) ;
  386. operation.SendFrame(*t_List) ;
  387. }
  388. if ( a_SnmpErrorReport.GetIndex () < vbl.GetLength () )
  389. {
  390. SnmpVarBindList *t_Cdr = vbl.Cdr ( a_SnmpErrorReport.GetIndex () - 1 ) ;
  391. VBList *t_List = new VBList (
  392. operation.session.GetSnmpEncodeDecode () ,
  393. *t_Cdr,
  394. vblist->GetIndex () + a_SnmpErrorReport.GetIndex ()
  395. ) ;
  396. operation.SendFrame(*t_List) ;
  397. }
  398. // re-send the frame using the old frame_state
  399. delete frame_state ;
  400. }
  401. return;
  402. }
  403. else
  404. {
  405. VBList *vblist = frame_state->GetVBList();
  406. SnmpVarBind *errored_vb;
  407. try
  408. {
  409. errored_vb = vblist->Remove(a_SnmpErrorReport.GetIndex () );
  410. }
  411. catch ( Heap_Exception e_He )
  412. {
  413. operation.ReceiveErroredResponse(
  414. frame_state->GetVBList()->GetIndex () ,
  415. frame_state->GetVBList()->GetVarBindList(),
  416. GeneralException(Snmp_Error, Snmp_Local_Error,__FILE__,__LINE__)
  417. );
  418. delete &frame_state;
  419. return;
  420. }
  421. catch(GeneralException exception)
  422. {
  423. operation.ReceiveErroredResponse(
  424. frame_state->GetVBList()->GetIndex () ,
  425. frame_state->GetVBList()->GetVarBindList(),
  426. exception
  427. );
  428. delete &frame_state;
  429. return;
  430. }
  431. // *** (SnmpStatus) casting
  432. SnmpErrorReport report(Snmp_Error, a_SnmpErrorReport.GetStatus () , a_SnmpErrorReport.GetIndex () );
  433. operation.ReceiveErroredVarBindResponse(
  434. vblist->GetIndex () + a_SnmpErrorReport.GetIndex () - 1 ,
  435. *errored_vb,
  436. report
  437. );
  438. delete errored_vb;
  439. SnmpErrorReport t_SnmpErrorReport ;
  440. operation.ReceiveErroredResponse(
  441. vblist->GetIndex () + a_SnmpErrorReport.GetIndex () - 1 ,
  442. frame_state->GetVBList()->GetVarBindList(),
  443. t_SnmpErrorReport
  444. );
  445. // destroy the frame_state: since the only case when the
  446. // old frame_state is reused is when there is an error
  447. // in a particular index and we wouldn't have come here in that case
  448. delete frame_state;
  449. return ;
  450. }
  451. }
  452. // otherwise, check the error status
  453. switch(a_SnmpErrorReport.GetStatus () )
  454. {
  455. case SNMP_ERROR_NOERROR:
  456. {
  457. // call ReceiveResponse for each vb
  458. ReceiveResponse (
  459. frame_state->GetVBList()->GetIndex (),
  460. frame_state->GetVBList()->GetVarBindList(),
  461. a_SnmpVarBindList ,
  462. a_SnmpErrorReport
  463. );
  464. }
  465. break;
  466. case SNMP_ERROR_TOOBIG:
  467. {
  468. if ( operation.GetPduType () != SnmpEncodeDecode :: PduType :: SET )
  469. {
  470. // callback FrameTooBig()
  471. operation.FrameTooBig();
  472. // check if the callback cancelled the operation
  473. if ( ! operation.in_progress )
  474. return;
  475. // obtain the list, length
  476. SnmpVarBindList &list = frame_state->GetVBList()->GetVarBindList();
  477. UINT length = list.GetLength();
  478. // if the length is 1, call ReceiveErroredResponse
  479. if ( length == 1 )
  480. {
  481. // *** casting Snmp_Status ***
  482. SnmpErrorReport report(Snmp_Error, a_SnmpErrorReport.GetStatus () , a_SnmpErrorReport.GetIndex () );
  483. operation.ReceiveErroredVarBindResponse(
  484. frame_state->GetVBList()->GetIndex () + a_SnmpErrorReport.GetIndex () - 1 ,
  485. *(list[1]),
  486. report
  487. );
  488. }
  489. else // split the list midway and send both fragments
  490. {
  491. operation.SendVarBindList(
  492. list,
  493. (length/2),
  494. frame_state->GetVBList()->GetIndex () + a_SnmpErrorReport.GetIndex () - 1
  495. );
  496. }
  497. }
  498. else
  499. {
  500. // *** casting Snmp_Status ***
  501. SnmpErrorReport report(Snmp_Error, a_SnmpErrorReport.GetStatus () , a_SnmpErrorReport.GetIndex ());
  502. // for each varbind in varbindlist
  503. // call ReceiveResponse for each vb
  504. operation.ReceiveErroredResponse(
  505. frame_state->GetVBList()->GetIndex (),
  506. frame_state->GetVBList()->GetVarBindList(),
  507. report
  508. );
  509. }
  510. }
  511. break;
  512. default:
  513. {
  514. // *** casting Snmp_Status ***
  515. SnmpErrorReport report(Snmp_Error, a_SnmpErrorReport.GetStatus () , a_SnmpErrorReport.GetIndex ());
  516. // for each varbind in varbindlist
  517. // call ReceiveResponse for each vb
  518. operation.ReceiveErroredResponse(
  519. frame_state->GetVBList()->GetIndex (),
  520. frame_state->GetVBList()->GetVarBindList(),
  521. report
  522. );
  523. }
  524. break;
  525. }
  526. // destroy the frame_state: since the only case when the
  527. // old frame_state is reused is when there is an error
  528. // in a particular index and we wouldn't have come here in that case
  529. delete frame_state;
  530. }