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.

476 lines
16 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. PROVSNMP.CPP
  5. Abstract:
  6. Purpose: Defines the acutal "Put" and "Get" functions for the
  7. "SNMP" file provider. The syntax of the mapping string is;
  8. "TBD"
  9. History:
  10. TBD 4-5-96 v0.01.
  11. --*/
  12. #include "precomp.h"
  13. #include "stdafx.h"
  14. #include <wbemidl.h>
  15. #include "impdyn.h"
  16. // This max size just prevents the read from incrementing to the point
  17. // where CStrings no longer work
  18. #define MAXSIZE 0x4FFF
  19. //SNMP specific constants
  20. #define TIMEOUT 500
  21. #define RETRIES 3
  22. #define IPADDRESSSTRLEN 16
  23. //Indexes of SNMP parameters in the provider string
  24. #define AGENT_INX 0
  25. #define COMMUNITY_INX 1
  26. #define OID_INX 2
  27. BYTE HEXCHAR[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  28. BOOL IsDisplayable(AsnOctetString OctetString)
  29. {
  30. BYTE *p;
  31. UINT i;
  32. for (i=0, p=OctetString.stream;
  33. ((i<OctetString.length) && ((*p >= 0x20) && (*p <= 0x7E)));
  34. i++, p++);
  35. if (i == OctetString.length)
  36. return(TRUE);
  37. else
  38. return(FALSE);
  39. }
  40. //***************************************************************************
  41. //
  42. // CImpSNMP::CImpSNMP
  43. //
  44. // Constructor. Only current purpose is to call its base class constructor.
  45. //
  46. //***************************************************************************
  47. CImpSNMP::CImpSNMP(LPUNKNOWN pUnkOuter) : CImpDyn(pUnkOuter)
  48. {
  49. return;
  50. }
  51. //***************************************************************************
  52. //
  53. // CImpSNMP::StartBatch
  54. //
  55. // Called at the start of a batch of gets or puts.
  56. // Retrieve agent & community from first provider string (ignore all other)
  57. // and open a session with this agent for SNMP requests.
  58. //
  59. //***************************************************************************
  60. void CImpSNMP::StartBatch(MODYNPROP * pMo,CObject **pObj,DWORD dwListSize,BOOL bGet)
  61. {
  62. TCHAR *agentStr; //IP address as String
  63. TCHAR *communityStr; //Community String
  64. *pObj = NULL;
  65. generalError = 0;
  66. Session = NULL;
  67. //Reset variable binding list
  68. variableBindings.list = NULL;
  69. variableBindings.len = 0;
  70. TCHAR * pMapString;
  71. #ifdef UNICODE
  72. pMapString = pMo->pProviderString;
  73. #else
  74. pMapString = WideToNarrow(pMo->pProviderString);
  75. #endif
  76. //Retrieve agent & community information from 1st property structure :
  77. //Create token object and make sure it has enough tokens
  78. CProvObj ProvObj(pMapString,MAIN_DELIM);
  79. if(ProvObj.dwGetStatus() != WBEM_NO_ERROR)
  80. {
  81. generalError = ProvObj.dwGetStatus();
  82. return;
  83. }
  84. if(ProvObj.iGetNumTokens() < iGetMinTokens())
  85. {
  86. generalError = M_MISSING_INFORMATION;
  87. return;
  88. }
  89. //Provider string seems OK -
  90. //Extract agent address & community name and open SNMP session with agent
  91. agentStr = new TCHAR[lstrlen(ProvObj.sGetToken(AGENT_INX))+1];
  92. //(TCHAR *)CoTaskMemAlloc(lstrlen(ProvObj.sGetToken(AGENT_INX))+1);
  93. if (agentStr == NULL)
  94. {
  95. generalError = WBEM_E_OUT_OF_MEMORY;
  96. return;
  97. }
  98. lstrcpy(agentStr, ProvObj.sGetToken(AGENT_INX));
  99. communityStr = new TCHAR[lstrlen(ProvObj.sGetToken(COMMUNITY_INX))+1];
  100. //(TCHAR *)CoTaskMemAlloc(lstrlen(ProvObj.sGetToken(COMMUNITY_INX)));
  101. if (communityStr == NULL)
  102. {
  103. generalError = WBEM_E_OUT_OF_MEMORY;
  104. delete agentStr;
  105. //CoTaskMemFree(agentStr);
  106. return;
  107. }
  108. lstrcpy(communityStr, ProvObj.sGetToken(COMMUNITY_INX));
  109. Session = SnmpMgrOpen(agentStr, communityStr, TIMEOUT, RETRIES);
  110. if (Session == NULL) //error
  111. {
  112. generalError = GetLastError();
  113. delete agentStr; delete communityStr;
  114. //CoTaskMemFree(agentStr); CoTaskMemFree(communityStr);
  115. return;
  116. }
  117. //Set requestType value
  118. requestType = (bGet ? ASN_RFC1157_GETREQUEST : ASN_RFC1157_SETREQUEST);
  119. //Free allocated buffers for agent & community - not needed once the session is open
  120. delete agentStr; delete communityStr;
  121. //CoTaskMemFree(agentStr); CoTaskMemFree(communityStr);
  122. //Free pMapString
  123. #ifndef UNICODE
  124. if(pMapString)
  125. CoTaskMemFree(pMapString);
  126. #endif
  127. return;
  128. }
  129. //***************************************************************************
  130. //
  131. // CImpSNMP::EndBatch
  132. //
  133. // Called at the end of a batch of gets or puts.
  134. // At this point we should have a valid session open and a variable binding
  135. // constructed. If so, send the SNMP request, and after receiving the answer
  136. // close the session with this agent.
  137. //
  138. //***************************************************************************
  139. void CImpSNMP::EndBatch(MODYNPROP *pMo,CObject *pObj,DWORD dwListSize,BOOL bGet)
  140. {
  141. AsnInteger errorStatus;
  142. AsnInteger errorIndex;
  143. DWORD reqCnt;
  144. DWORD varBindCnt;
  145. DWORD allocatedLength;
  146. //temps to hold values for conversion
  147. AsnObjectSyntax *SNMPValue;
  148. BYTE *OLESMValue;
  149. if ((Session == NULL) || (generalError != 0))
  150. return;
  151. //Carry out request
  152. if (!SnmpMgrRequest(Session, requestType, &variableBindings, &errorStatus, &errorIndex))
  153. //API error occured
  154. generalError = GetLastError();
  155. varBindCnt = 0;
  156. for (reqCnt = 0; reqCnt < dwListSize; reqCnt++, pMo++)
  157. {
  158. //if request failed above, need to set all dwResults to the failure code
  159. if (generalError != 0)
  160. {
  161. pMo->dwResult = generalError;
  162. continue;
  163. }
  164. //if dwResult was already set to an error, this request was not sent in the SNMP message
  165. // in the first place, so skip to the next one
  166. if (pMo->dwResult != WBEM_NO_ERROR)
  167. continue;
  168. if (errorStatus != SNMP_ERRORSTATUS_NOERROR)
  169. {
  170. //There was an SNMP error - no values are returned
  171. pMo->pPropertyValue = NULL;
  172. pMo->dwResult = WBEM_E_FAILED;
  173. //should I return specific SNMP error ?????
  174. //the errorIndex information is lost here !!!!
  175. continue;
  176. }
  177. //Value is valid - try converting to supported types
  178. SNMPValue = &(variableBindings.list[varBindCnt].value);
  179. generalError = CopySNMPValToOLESMVal(SNMPValue, &OLESMValue, pMo->dwType, &allocatedLength);
  180. if (generalError != 0)
  181. { //error detected when converting types
  182. pMo->pPropertyValue = NULL;
  183. pMo->dwBufferSize = 0;
  184. pMo->dwResult = generalError;
  185. }
  186. else
  187. { //types converted OK, so OLESMValue is pointing to the newly allocated value
  188. pMo->pPropertyValue = OLESMValue;
  189. pMo->dwBufferSize = allocatedLength;
  190. pMo->dwResult = WBEM_NO_ERROR;
  191. }
  192. varBindCnt++;
  193. }//for
  194. //Free variable bindings structure
  195. if (variableBindings.list != NULL)
  196. CoTaskMemFree(variableBindings.list);
  197. //Close session with agent (don't check status since we can't return error anyway....????)
  198. SnmpMgrClose(Session);
  199. return;
  200. }//EndBatch
  201. //***************************************************************************
  202. //
  203. // CImpSNMP::GetProp
  204. //
  205. // Builds a variable binding for the current property
  206. //
  207. //***************************************************************************
  208. void CImpSNMP::GetProp(MODYNPROP * pMo, CProvObj & ProvObj,CObject * pPackage)
  209. {
  210. TCHAR * oidStr;
  211. AsnObjectIdentifier reqObject;
  212. pMo->dwResult = WBEM_NO_ERROR; //To be checked in EndBatch()
  213. //If Session is not open - error !
  214. if ((Session == NULL) || (generalError != 0))
  215. {
  216. pMo->dwResult = generalError;
  217. return;
  218. }
  219. //Extract OID of property from provider string
  220. oidStr = new TCHAR[lstrlen(ProvObj.sGetToken(OID_INX))+1];
  221. //(TCHAR *)CoTaskMemAlloc(lstrlen(ProvObj.sGetToken(OID_INX)));
  222. if (oidStr == NULL)
  223. {
  224. pMo->dwResult = WBEM_E_OUT_OF_MEMORY;
  225. return;
  226. }
  227. lstrcpy(oidStr, ProvObj.sGetToken(OID_INX)); //oid is the 3rd parameter in the provider string
  228. //Convert string representation of OID to internal rep.
  229. if (!SnmpMgrStrToOid(oidStr, &reqObject))
  230. {
  231. pMo->dwResult = M_MISSING_INFORMATION;
  232. delete oidStr;
  233. //CoTaskMemFree(oidStr);
  234. return;
  235. }
  236. //If conversion successful, free OID string - not needed once we have the OID in internal rep.
  237. delete oidStr;
  238. //CoTaskMemFree(oidStr);
  239. //Allocate new variable binding in list
  240. variableBindings.list =
  241. (RFC1157VarBind *)CoTaskMemRealloc(variableBindings.list,
  242. sizeof(RFC1157VarBind) * (variableBindings.len+1));
  243. if (variableBindings.list == NULL) //allocation failed
  244. {
  245. pMo->dwResult = WBEM_E_OUT_OF_MEMORY;
  246. return;
  247. }
  248. //if allocation succesful, copy info to new variable binding
  249. variableBindings.len++;
  250. variableBindings.list[variableBindings.len - 1].name = reqObject; //structure copy !!
  251. variableBindings.list[variableBindings.len - 1].value.asnType = ASN_NULL;
  252. return;
  253. }//GetProp
  254. //***************************************************************************
  255. //
  256. // CImpSNMP::SetProp
  257. //
  258. // Writes the value of a single property
  259. //
  260. //***************************************************************************
  261. void CImpSNMP::SetProp(MODYNPROP * pMo, CProvObj & ProvObj,CObject * pPackage)
  262. {
  263. CString sString;
  264. sString = ProvObj.sGetToken(0);
  265. pMo->dwResult = 0 ;
  266. return;
  267. }
  268. //***************************************************************************
  269. //
  270. // CImpSNMP::CopySNMPValToOLESMVal
  271. //
  272. // Converts an SNMP value to an OLESM supported type, allocates and sets
  273. // the value in the property structure.
  274. // The pLen parameter outputs the length of the allocated memory
  275. // The return value specifies the outcome of the function (0 for success)
  276. //
  277. //***************************************************************************
  278. DWORD CImpSNMP::CopySNMPValToOLESMVal(AsnAny *fromVal, BYTE **pToVal, DWORD OLESMType, DWORD *pLen)
  279. {
  280. DWORD ret = WBEM_NO_ERROR;
  281. UINT i;
  282. BYTE *pSrc, *pDst;
  283. switch (OLESMType)
  284. {
  285. case M_TYPE_DWORD :
  286. if ((fromVal->asnType == ASN_INTEGER) || (fromVal->asnType == ASN_RFC1155_COUNTER) ||
  287. (fromVal->asnType == ASN_RFC1155_GAUGE) || (fromVal->asnType == ASN_RFC1155_TIMETICKS))
  288. {
  289. if (!(*pToVal = (BYTE *)CoTaskMemAlloc(sizeof(DWORD))))
  290. ret = WBEM_E_OUT_OF_MEMORY;
  291. else
  292. { //allocation succeeded
  293. *pLen = sizeof(DWORD);
  294. switch (fromVal->asnType)
  295. {
  296. case ASN_INTEGER : *(DWORD *)(*pToVal) = fromVal->asnValue.number; break;
  297. case ASN_RFC1155_COUNTER : *(DWORD *)(*pToVal) = fromVal->asnValue.counter; break;
  298. case ASN_RFC1155_GAUGE : *(DWORD *)(*pToVal) = fromVal->asnValue.gauge; break;
  299. case ASN_RFC1155_TIMETICKS : *(DWORD *)(*pToVal) = fromVal->asnValue.ticks; break;
  300. default : break;
  301. }
  302. }
  303. }
  304. else
  305. ret = M_TYPE_MISMATCH;
  306. break;
  307. case M_TYPE_LPSTR :
  308. switch (fromVal->asnType)
  309. {
  310. case ASN_OCTETSTRING :
  311. if (IsDisplayable(fromVal->asnValue.string))
  312. //Need to add '\0' only
  313. if (!(*pToVal = (BYTE *)CoTaskMemAlloc(fromVal->asnValue.string.length+1)))
  314. ret = WBEM_E_OUT_OF_MEMORY;
  315. else
  316. { //allocation succeeded
  317. *pLen = fromVal->asnValue.string.length+1;
  318. memcpy(*pToVal, fromVal->asnValue.string.stream, fromVal->asnValue.string.length);
  319. *(*pToVal + (*pLen-1)) = '\0';
  320. }
  321. else //String is stream of bytes (non-displayable)
  322. //Need to copy non-displayable characters to "^XX" format
  323. //Allocate 3 chars for every byte in the stream + '\0'
  324. if (!(*pToVal = (BYTE *)CoTaskMemAlloc((fromVal->asnValue.string.length * 3) + 1)))
  325. ret = WBEM_E_OUT_OF_MEMORY;
  326. else
  327. { //allocation succeeded
  328. *pLen = (fromVal->asnValue.string.length * 3) + 1;
  329. for (i=0, pSrc=fromVal->asnValue.string.stream, pDst=*pToVal;
  330. i<fromVal->asnValue.string.length;
  331. i++, pSrc++)
  332. {
  333. *(pDst++) = '^';
  334. *(pDst++) = HEXCHAR[(*pSrc & 0x0F)];
  335. *(pDst++) = HEXCHAR[((*pSrc & 0xF0) >> 4)];
  336. }
  337. *(*pToVal + (*pLen-1)) = '\0';
  338. }
  339. break;
  340. case ASN_OBJECTIDENTIFIER :
  341. {
  342. TCHAR *oidStr = NULL;
  343. SnmpMgrOidToStr(&(fromVal->asnValue.object), &oidStr);
  344. if (!oidStr)
  345. ret = WBEM_E_OUT_OF_MEMORY;
  346. else
  347. {
  348. if (!(*pToVal = (BYTE *)CoTaskMemAlloc(lstrlen(oidStr)+1)))
  349. ret = WBEM_E_OUT_OF_MEMORY;
  350. else
  351. {
  352. *pLen = lstrlen(oidStr)+1;
  353. memcpy(*pToVal, oidStr, *pLen);
  354. }
  355. GlobalFree(oidStr);
  356. }
  357. }
  358. break;
  359. case ASN_SEQUENCE :
  360. if (!(*pToVal = (BYTE *)CoTaskMemAlloc(fromVal->asnValue.sequence.length)))
  361. ret = WBEM_E_OUT_OF_MEMORY;
  362. else
  363. {
  364. *pLen = fromVal->asnValue.sequence.length;
  365. memcpy(*pToVal, fromVal->asnValue.sequence.stream, fromVal->asnValue.sequence.length);
  366. }
  367. break;
  368. case ASN_RFC1155_IPADDRESS :
  369. //allocate a string for string representation of IP address
  370. if (!(*pToVal = (BYTE *)CoTaskMemAlloc(IPADDRESSSTRLEN)))
  371. ret = WBEM_E_OUT_OF_MEMORY;
  372. else
  373. { //allocation succeeded
  374. //Copy IP address to formatted string
  375. sprintf((TCHAR *)*pToVal, "%u.%u.%u.%u\0", *(fromVal->asnValue.address.stream),
  376. *(fromVal->asnValue.address.stream+1),
  377. *(fromVal->asnValue.address.stream+2),
  378. *(fromVal->asnValue.address.stream+3));
  379. *pLen = lstrlen((TCHAR *)*pToVal)+1;
  380. //*pLen = fromVal->asnValue.address.length;
  381. //memcpy(*pToVal, fromVal->asnValue.address.stream, fromVal->asnValue.address.length);
  382. }
  383. break;
  384. case ASN_RFC1155_OPAQUE :
  385. if (!(*pToVal = (BYTE *)CoTaskMemAlloc(fromVal->asnValue.arbitrary.length)))
  386. ret = WBEM_E_OUT_OF_MEMORY;
  387. else
  388. {
  389. *pLen = fromVal->asnValue.arbitrary.length;
  390. memcpy(*pToVal, fromVal->asnValue.arbitrary.stream, fromVal->asnValue.arbitrary.length);
  391. }
  392. break;
  393. default :
  394. ret = M_TYPE_MISMATCH;
  395. break;
  396. }
  397. break;
  398. default :
  399. ret = M_TYPE_NOT_SUPPORTED;
  400. break;
  401. }//switch (OLESMType)
  402. if (ret != WBEM_NO_ERROR) //error
  403. {
  404. *pToVal = NULL;
  405. *pLen = 0;
  406. }
  407. return(ret);
  408. }//CopySNMPValToOLESMVal()