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.

584 lines
19 KiB

  1. /*****************************************************************************
  2. *
  3. * $Workfile: SnmpMgr.cpp $
  4. *
  5. * Copyright (C) 1997 Hewlett-Packard Company.
  6. * Copyright (C) 1997 Microsoft Corporation.
  7. * All rights reserved.
  8. *
  9. * 11311 Chinden Blvd.
  10. * Boise, Idaho 83714
  11. *
  12. *****************************************************************************/
  13. #include "precomp.h"
  14. #include "stdoids.h"
  15. #include "snmpmgr.h"
  16. ///////////////////////////////////////////////////////////////////////////////
  17. // CSnmpMgr::CSnmpMgr()
  18. CSnmpMgr::CSnmpMgr() :
  19. m_pAgent(NULL), m_pCommunity(NULL),m_pSession(NULL),
  20. m_iLastError(NO_ERROR), m_iRetries(DEFAULT_RETRIES),
  21. m_iTimeout(DEFAULT_TIMEOUT),
  22. m_bRequestType(DEFAULT_SNMP_REQUEST)
  23. {
  24. } // ::CSnmpMgr()
  25. ///////////////////////////////////////////////////////////////////////////////
  26. // CSnmpMgr::CSnmpMgr() -- establishes a session w/ a given agent
  27. // uses the default request type (get) & community name (public)
  28. CSnmpMgr::CSnmpMgr( const char in *pHost,
  29. const char in *pCommunity,
  30. DWORD dwDevIndex ) :
  31. m_pAgent(NULL), m_pCommunity(NULL),m_pSession(NULL),
  32. m_iLastError(NO_ERROR), m_iRetries(DEFAULT_RETRIES),
  33. m_iTimeout(DEFAULT_TIMEOUT),
  34. m_bRequestType(DEFAULT_SNMP_REQUEST)
  35. {
  36. size_t cchAgent = strlen(pHost) + 1;
  37. m_pAgent = (LPSTR)SNMP_malloc(cchAgent * sizeof m_pAgent [0]); // copy the agent
  38. if( m_pAgent != NULL )
  39. {
  40. StringCchCopyA (m_pAgent, cchAgent, pHost);
  41. }
  42. size_t cchCommunity = strlen(pCommunity) + 1;
  43. m_pCommunity = (LPSTR)SNMP_malloc(cchCommunity * sizeof m_pCommunity [0]); // copy the community name
  44. if( m_pCommunity != NULL )
  45. {
  46. StringCchCopyA (m_pCommunity, cchCommunity, pCommunity);
  47. }
  48. m_bRequestType = DEFAULT_SNMP_REQUEST; // set the default request type == GET request
  49. m_pSession = NULL;
  50. if ( !Open() ) // establish a session w/ the agent
  51. {
  52. m_iLastError = GetLastError();
  53. }
  54. } // ::CSnmpMgr()
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // CSnmpMgr::CSnmpMgr() -- establishes a session w/ a given agent
  57. // uses the default request type (get) & community name (public)
  58. CSnmpMgr::CSnmpMgr( const char in *pHost,
  59. const char in *pCommunity,
  60. DWORD in dwDevIndex,
  61. AsnObjectIdentifier in *pMibObjId,
  62. RFC1157VarBindList out *pVarBindList) :
  63. m_pAgent(NULL), m_pCommunity(NULL),m_pSession(NULL),
  64. m_iLastError(NO_ERROR), m_iRetries(DEFAULT_RETRIES),
  65. m_iTimeout(DEFAULT_TIMEOUT),
  66. m_bRequestType(DEFAULT_SNMP_REQUEST)
  67. {
  68. DWORD dwRetCode = SNMPAPI_NOERROR;
  69. size_t cchAgent = strlen(pHost) + 1;
  70. m_pAgent = (LPSTR)SNMP_malloc(cchAgent * sizeof m_pAgent [0]); // copy the agent
  71. if( m_pAgent != NULL )
  72. {
  73. StringCchCopyA (m_pAgent, cchAgent, pHost);
  74. }
  75. size_t cchCommunity = strlen(pCommunity) + 1;
  76. m_pCommunity = (LPSTR)SNMP_malloc(cchCommunity * sizeof m_pCommunity [0]); // copy the community name
  77. if( m_pCommunity != NULL )
  78. {
  79. StringCchCopyA (m_pCommunity, cchCommunity, pCommunity);
  80. }
  81. m_bRequestType = DEFAULT_SNMP_REQUEST; // set the default request type == GET request
  82. dwRetCode = BldVarBindList(pMibObjId, pVarBindList);
  83. if (dwRetCode == SNMPAPI_NOERROR)
  84. {
  85. m_pSession = NULL;
  86. if ( !Open() ) // establish a session w/ the agent
  87. {
  88. m_iLastError = GetLastError();
  89. }
  90. }
  91. } // ::CSnmpMgr()
  92. ///////////////////////////////////////////////////////////////////////////////
  93. // CSnmpMgr::~CSnmpMgr()
  94. CSnmpMgr::~CSnmpMgr()
  95. {
  96. if (m_pSession) Close(); // close the session
  97. // delete the allocated memory from community & agent names
  98. if (m_pAgent) SNMP_free(m_pAgent);
  99. if (m_pCommunity) SNMP_free(m_pCommunity);
  100. } // ::~CSnmpMgr()
  101. ///////////////////////////////////////////////////////////////////////////////
  102. // Open() -- establishes a session
  103. // Error Codes:
  104. // SNMPAPI_NOERROR if successful
  105. // SNMPAPI_ERROR if fails
  106. BOOL
  107. CSnmpMgr::Open()
  108. {
  109. m_iLastError = SNMPAPI_NOERROR;
  110. m_pSession = SnmpMgrOpen(m_pAgent, m_pCommunity, m_iTimeout, m_iRetries);
  111. if ( m_pSession == NULL )
  112. {
  113. m_iLastError = SNMPAPI_ERROR;
  114. m_pSession = NULL;
  115. return FALSE;
  116. }
  117. return TRUE;
  118. } // ::Open()
  119. ///////////////////////////////////////////////////////////////////////////////
  120. // Close() -- closes the previously established session
  121. void
  122. CSnmpMgr::Close()
  123. {
  124. _ASSERTE( m_pSession != NULL);
  125. if ( !SnmpMgrClose(m_pSession) )
  126. {
  127. m_iLastError = GetLastError();
  128. }
  129. m_pSession = NULL;
  130. } // ::Close()
  131. ///////////////////////////////////////////////////////////////////////////////
  132. // Get() -- does an SNMP command (m_bRequestType) given a set of OIDs
  133. // Error Codes:
  134. // SNMP_ERRORSTATUS_NOERROR if no error
  135. // SNMP_ERRORSTATUS_TOOBIG if the packet returned is big
  136. // SNMP_ERRORSTATUS_NOSUCHNAME if the OID isn't supported
  137. // SNMP_ERRORSTATUS_BADVALUE
  138. // SNMP_ERRORSTATUS_READONLY
  139. // SNMP_ERRORSTATUS_GENERR
  140. // SNMP_MGMTAPI_TIMEOUT -- set by GetLastError()
  141. // SNMP_MGMTAPI_SELECT_FDERRORS -- set by GetLastError()
  142. int
  143. CSnmpMgr::Get( RFC1157VarBindList in *pVariableBindings)
  144. {
  145. int iRetCode = SNMP_ERRORSTATUS_NOERROR;
  146. AsnInteger errorStatus;
  147. AsnInteger errorIndex;
  148. if ( !SnmpMgrRequest( m_pSession, m_bRequestType, pVariableBindings, &errorStatus, &errorIndex) )
  149. {
  150. iRetCode = m_iLastError = GetLastError();
  151. }
  152. else
  153. {
  154. if (errorStatus > 0)
  155. {
  156. iRetCode = errorStatus;
  157. }
  158. else // return the result of the variable bindings?
  159. {
  160. // variableBindings->list[x]->value contains the return value
  161. }
  162. }
  163. return iRetCode;
  164. } // ::Get()
  165. ///////////////////////////////////////////////////////////////////////////////
  166. // Walk -- given an object, it walks until the tree is done
  167. // Error Codes:
  168. // SNMP_ERRORSTATUS_TOOBIG if the packet returned is big
  169. // SNMP_ERRORSTATUS_NOSUCHNAME if the OID isn't supported
  170. // SNMP_ERRORSTATUS_BADVALUE
  171. // SNMP_ERRORSTATUS_READONLY
  172. // SNMP_ERRORSTATUS_GENERR
  173. // SNMP_MGMTAPI_TIMEOUT -- set by GetLastError()
  174. // SNMP_MGMTAPI_SELECT_FDERRORS -- set by GetLastError()
  175. int
  176. CSnmpMgr::Walk( RFC1157VarBindList inout *pVariableBindings)
  177. {
  178. int iRetCode = SNMP_ERRORSTATUS_NOERROR;
  179. RFC1157VarBindList variableBindings;
  180. UINT numElements=0;
  181. LPVOID pTemp;
  182. variableBindings.len = 0;
  183. variableBindings.list = NULL;
  184. variableBindings.len++;
  185. if ( (variableBindings.list = (RFC1157VarBind *)SNMP_realloc(variableBindings.list,
  186. sizeof(RFC1157VarBind) * variableBindings.len)) == NULL)
  187. {
  188. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  189. return iRetCode;
  190. }
  191. if ( !SnmpUtilVarBindCpy(&(variableBindings.list[variableBindings.len -1]), &(pVariableBindings->list[0])) )
  192. {
  193. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  194. return iRetCode;
  195. }
  196. AsnObjectIdentifier root;
  197. AsnObjectIdentifier tempOid;
  198. AsnInteger errorStatus;
  199. AsnInteger errorIndex;
  200. if (!SnmpUtilOidCpy(&root, &variableBindings.list[0].name))
  201. {
  202. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  203. goto CleanUp;
  204. }
  205. m_bRequestType = ASN_RFC1157_GETNEXTREQUEST;
  206. while(1) // walk the MIB tree (or sub-tree)
  207. {
  208. if (!SnmpMgrRequest(m_pSession, m_bRequestType, &variableBindings,
  209. &errorStatus, &errorIndex))
  210. {
  211. // The API is indicating an error.
  212. iRetCode = m_iLastError = GetLastError();
  213. break;
  214. }
  215. else
  216. {
  217. // The API succeeded, errors may be indicated from the remote agent.
  218. // Test for end of subtree or end of MIB.
  219. if (errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME ||
  220. SnmpUtilOidNCmp(&variableBindings.list[0].name, &root, root.idLength))
  221. {
  222. iRetCode = SNMP_ERRORSTATUS_NOSUCHNAME;
  223. break;
  224. }
  225. // Test for general error conditions or sucesss.
  226. if (errorStatus > 0)
  227. {
  228. iRetCode = errorStatus;
  229. break;
  230. }
  231. numElements++;
  232. } // end if()
  233. // append the variableBindings to the pVariableBindings
  234. _ASSERTE(pVariableBindings->len != 0);
  235. if ( ( pTemp = (RFC1157VarBind *)SNMP_realloc(pVariableBindings->list,
  236. sizeof(RFC1157VarBind) * (pVariableBindings->len + 1))) == NULL)
  237. {
  238. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  239. break;
  240. }
  241. else
  242. {
  243. pVariableBindings->list = (SnmpVarBind *)pTemp;
  244. pVariableBindings->len++;
  245. }
  246. if ( !SnmpUtilVarBindCpy(&(pVariableBindings->list[pVariableBindings->len -1]), &(variableBindings.list[0])) )
  247. {
  248. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  249. break;
  250. }
  251. // Prepare for the next iteration. Make sure returned oid is
  252. // preserved and the returned value is freed
  253. if( SnmpUtilOidCpy(&tempOid, &variableBindings.list[0].name) )
  254. {
  255. SnmpUtilVarBindFree(&variableBindings.list[0]);
  256. if ( SnmpUtilOidCpy(&variableBindings.list[0].name, &tempOid))
  257. {
  258. variableBindings.list[0].value.asnType = ASN_NULL;
  259. SnmpUtilOidFree(&tempOid);
  260. }
  261. else
  262. {
  263. iRetCode = SNMP_ERRORSTATUS_GENERR;
  264. goto CleanUp;
  265. }
  266. }
  267. else
  268. {
  269. iRetCode = SNMP_ERRORSTATUS_GENERR;
  270. goto CleanUp;
  271. }
  272. } // end while()
  273. CleanUp:
  274. // Free the variable bindings that have been allocated.
  275. SnmpUtilVarBindListFree(&variableBindings);
  276. SnmpUtilOidFree(&root);
  277. if (iRetCode == SNMP_ERRORSTATUS_NOSUCHNAME)
  278. if (numElements != 0) // list is full; iRetCode indicates the end of the MIB
  279. iRetCode = SNMP_ERRORSTATUS_NOERROR;
  280. return (iRetCode);
  281. } // Walk()
  282. ///////////////////////////////////////////////////////////////////////////////
  283. // WalkNext -- given object(s), it walks until the table has no more object
  284. // entries. The end of the table is determined by the first item in the list.
  285. // Error Codes:
  286. // SNMP_ERRORSTATUS_TOOBIG if the packet returned is big
  287. // SNMP_ERRORSTATUS_NOSUCHNAME if the OID isn't supported
  288. // SNMP_ERRORSTATUS_BADVALUE
  289. // SNMP_ERRORSTATUS_READONLY
  290. // SNMP_ERRORSTATUS_GENERR
  291. // SNMP_MGMTAPI_TIMEOUT -- set by GetLastError()
  292. // SNMP_MGMTAPI_SELECT_FDERRORS -- set by GetLastError()
  293. int
  294. CSnmpMgr::WalkNext( RFC1157VarBindList inout *pVariableBindings)
  295. {
  296. int iRetCode = SNMP_ERRORSTATUS_NOERROR;
  297. RFC1157VarBindList variableBindings;
  298. UINT numElements=0;
  299. UINT len=0, i=0;
  300. LPVOID pTemp;
  301. variableBindings.len = 0;
  302. variableBindings.list = NULL;
  303. variableBindings.len = pVariableBindings->len;
  304. if ( (variableBindings.list = (RFC1157VarBind *)SNMP_realloc(variableBindings.list,
  305. sizeof(RFC1157VarBind) * variableBindings.len)) == NULL)
  306. {
  307. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  308. return iRetCode;
  309. }
  310. for (i=0; i<variableBindings.len; i++)
  311. {
  312. if ( !SnmpUtilVarBindCpy(&(variableBindings.list[i]), &(pVariableBindings->list[i])) )
  313. {
  314. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  315. return iRetCode;
  316. }
  317. }
  318. AsnObjectIdentifier root;
  319. AsnObjectIdentifier tempOid;
  320. AsnInteger errorStatus;
  321. AsnInteger errorIndex;
  322. if (!SnmpUtilOidCpy(&root, &variableBindings.list[0].name))
  323. {
  324. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  325. goto CleanUp;
  326. }
  327. m_bRequestType = ASN_RFC1157_GETNEXTREQUEST;
  328. while(1) // get the object(s) in the MIB table
  329. {
  330. if (!SnmpMgrRequest(m_pSession, m_bRequestType, &variableBindings,
  331. &errorStatus, &errorIndex))
  332. {
  333. // The API is indicating an error.
  334. iRetCode = m_iLastError = GetLastError();
  335. break;
  336. }
  337. else
  338. {
  339. // The API succeeded, errors may be indicated from the remote agent.
  340. // Test for end of subtree or end of MIB.
  341. if (errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME ||
  342. SnmpUtilOidNCmp(&variableBindings.list[0].name, &root, root.idLength))
  343. {
  344. iRetCode = SNMP_ERRORSTATUS_NOSUCHNAME;
  345. break;
  346. }
  347. // Test for general error conditions or sucesss.
  348. if (errorStatus > 0)
  349. {
  350. iRetCode = errorStatus;
  351. break;
  352. }
  353. numElements++;
  354. } // end if()
  355. // append the variableBindings to the pVariableBindings
  356. _ASSERTE(pVariableBindings->len != 0);
  357. len = pVariableBindings->len;
  358. if ( (pTemp = (RFC1157VarBind *)SNMP_realloc(pVariableBindings->list,
  359. sizeof(RFC1157VarBind) * (pVariableBindings->len + variableBindings.len))) == NULL)
  360. {
  361. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  362. break;
  363. }
  364. else
  365. {
  366. pVariableBindings->list = (SnmpVarBind *)pTemp;
  367. pVariableBindings->len += variableBindings.len;
  368. }
  369. int j=0;
  370. for ( i=len; i < pVariableBindings->len; i++, j++)
  371. {
  372. if ( !SnmpUtilVarBindCpy(&(pVariableBindings->list[i]), &(variableBindings.list[j])) )
  373. {
  374. iRetCode = ERROR_NOT_ENOUGH_MEMORY;
  375. break;
  376. }
  377. }
  378. // Prepare for the next iteration. Make sure returned oid is
  379. // preserved and the returned value is freed
  380. for (i=0; i<variableBindings.len; i++)
  381. {
  382. if ( SnmpUtilOidCpy(&tempOid, &variableBindings.list[i].name) )
  383. {
  384. SnmpUtilVarBindFree(&variableBindings.list[i]);
  385. if( SnmpUtilOidCpy(&variableBindings.list[i].name, &tempOid))
  386. {
  387. variableBindings.list[i].value.asnType = ASN_NULL;
  388. SnmpUtilOidFree(&tempOid);
  389. }
  390. else
  391. {
  392. iRetCode = SNMP_ERRORSTATUS_GENERR;
  393. goto CleanUp;
  394. }
  395. }
  396. else
  397. {
  398. iRetCode = SNMP_ERRORSTATUS_GENERR;
  399. goto CleanUp;
  400. }
  401. }
  402. } // end while()
  403. CleanUp:
  404. // Free the variable bindings that have been allocated.
  405. SnmpUtilVarBindListFree(&variableBindings);
  406. SnmpUtilOidFree(&root);
  407. if (iRetCode == SNMP_ERRORSTATUS_NOSUCHNAME)
  408. if (numElements != 0) // list is full; iRetCode indicates the end of the MIB
  409. iRetCode = SNMP_ERRORSTATUS_NOERROR;
  410. return (iRetCode);
  411. } // WalkNext()
  412. ///////////////////////////////////////////////////////////////////////////////
  413. // GetNext -- does an SNMP GetNext command on the set of OID(s)
  414. // Error Codes:
  415. // SNMP_ERRORSTATUS_TOOBIG if the packet returned is big
  416. // SNMP_ERRORSTATUS_NOSUCHNAME if the OID isn't supported
  417. // SNMP_ERRORSTATUS_BADVALUE
  418. // SNMP_ERRORSTATUS_READONLY
  419. // SNMP_ERRORSTATUS_GENERR
  420. // SNMP_MGMTAPI_TIMEOUT -- set by GetLastError()
  421. // SNMP_MGMTAPI_SELECT_FDERRORS -- set by GetLastError()
  422. int
  423. CSnmpMgr::GetNext( RFC1157VarBindList inout *pVariableBindings)
  424. {
  425. int iRetCode = SNMP_ERRORSTATUS_NOERROR;
  426. AsnInteger errorStatus;
  427. AsnInteger errorIndex;
  428. m_bRequestType = ASN_RFC1157_GETNEXTREQUEST;
  429. if ( !SnmpMgrRequest( m_pSession, m_bRequestType, pVariableBindings, &errorStatus, &errorIndex) )
  430. {
  431. iRetCode = m_iLastError = GetLastError();
  432. }
  433. else
  434. {
  435. if (errorStatus > 0)
  436. {
  437. iRetCode = errorStatus;
  438. }
  439. else // return the result of the variable bindings?
  440. {
  441. // variableBindings->list[x]->value contains the return value
  442. }
  443. }
  444. return (iRetCode);
  445. } // GetNext()
  446. ///////////////////////////////////////////////////////////////////////////////
  447. // BldVarBindList -- given a category, it retuns the RFC1157VarBindList
  448. // Error Codes:
  449. // NO_ERROR if successful
  450. // ERROR_NOT_ENOUGH_MEMORY if memory allocation failes
  451. // ERROR_INVALID_HANDLE if can't build the variable bindings
  452. DWORD
  453. CSnmpMgr::BldVarBindList( AsnObjectIdentifier in *pMibObjId, // group identifier
  454. RFC1157VarBindList inout *pVarBindList)
  455. {
  456. DWORD dwRetCode = SNMPAPI_NOERROR;
  457. LPVOID pTemp;
  458. m_iLastError = SNMPAPI_NOERROR;
  459. while (pMibObjId->idLength != 0)
  460. {
  461. // setup the variable bindings
  462. CONST UINT uNewLen = pVarBindList->len + 1;
  463. if ( (pTemp = (RFC1157VarBind *)SNMP_realloc(pVarBindList->list,
  464. sizeof(RFC1157VarBind) * uNewLen)) == NULL)
  465. {
  466. m_iLastError = ERROR_NOT_ENOUGH_MEMORY;
  467. return ERROR_NOT_ENOUGH_MEMORY;
  468. }
  469. else
  470. {
  471. pVarBindList->list = (SnmpVarBind *)pTemp;
  472. pVarBindList-> len = uNewLen;
  473. }
  474. AsnObjectIdentifier reqObject;
  475. if ( !SnmpUtilOidCpy(&reqObject, pMibObjId) )
  476. {
  477. m_iLastError = ERROR_INVALID_HANDLE;
  478. return ERROR_INVALID_HANDLE;
  479. }
  480. pVarBindList->list[pVarBindList->len -1].name = reqObject;
  481. pVarBindList->list[pVarBindList->len -1].value.asnType = ASN_NULL;
  482. pMibObjId++;
  483. }
  484. return dwRetCode;
  485. } // BldVarBindList