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.

656 lines
22 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1991-2001 Microsoft Corporation
  3. Module Name:
  4. snmputil.c
  5. Abstract:
  6. Sample SNMP Management API usage for Windows NT.
  7. This file is an example of how to code management applications using
  8. the SNMP Management API for Windows NT. It is similar in operation to
  9. the other commonly available SNMP command line utilities.
  10. Extensive comments have been included to describe its structure and
  11. operation. See also "Microsoft Windows NT SNMP Programmer's Reference".
  12. --*/
  13. // General notes:
  14. // Microsoft's SNMP Management API for Windows NT is implemented as a DLL
  15. // that is linked with the developer's code. These APIs (examples follow in
  16. // this file) allow the developer's code to generate SNMP queries and receive
  17. // SNMP traps. A simple MIB compiler and related APIs are also available to
  18. // allow conversions between OBJECT IDENTIFIERS and OBJECT DESCRIPTORS.
  19. // Necessary includes.
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <snmp.h>
  24. #include <mgmtapi.h>
  25. // Constants used in this example.
  26. #define GET 1
  27. #define GETNEXT 2
  28. #define WALK 3
  29. #define TRAP 4
  30. #define TIMEOUT 6000 /* milliseconds */
  31. #define RETRIES 0
  32. void
  33. SNMP_FUNC_TYPE AsnValueFree(
  34. IN AsnAny *asnValue
  35. )
  36. {
  37. // Free any data in the varbind value
  38. switch ( asnValue->asnType )
  39. {
  40. case ASN_OBJECTIDENTIFIER:
  41. SnmpUtilOidFree( &asnValue->asnValue.object );
  42. break;
  43. case ASN_RFC1155_IPADDRESS:
  44. case ASN_RFC1155_OPAQUE:
  45. case ASN_OCTETSTRING:
  46. if ( asnValue->asnValue.string.dynamic == TRUE )
  47. {
  48. SnmpUtilMemFree( asnValue->asnValue.string.stream );
  49. }
  50. break;
  51. default:
  52. break;
  53. // Purposefully do nothing, because no storage alloc'ed for others
  54. }
  55. // Set type to NULL
  56. asnValue->asnType = ASN_NULL;
  57. }
  58. // Main program.
  59. INT __cdecl main(
  60. IN int argumentCount,
  61. IN char *argumentVector[])
  62. {
  63. INT operation;
  64. LPSTR agent;
  65. LPSTR community;
  66. RFC1157VarBindList variableBindings;
  67. LPSNMP_MGR_SESSION session;
  68. INT timeout = TIMEOUT;
  69. INT retries = RETRIES;
  70. BYTE requestType;
  71. AsnInteger errorStatus;
  72. AsnInteger errorIndex;
  73. // Parse command line arguments to determine requested operation.
  74. // Verify number of arguments...
  75. if (argumentCount < 5 && argumentCount != 2)
  76. {
  77. printf("Error: Incorrect number of arguments specified.\n");
  78. printf(
  79. "\nusage: snmputil [get|getnext|walk] agent community oid [oid ...]\n");
  80. printf(
  81. " snmputil trap\n");
  82. return 1;
  83. }
  84. // Get/verify operation...
  85. argumentVector++;
  86. argumentCount--;
  87. if (!strcmp(*argumentVector, "get"))
  88. operation = GET;
  89. else if (!strcmp(*argumentVector, "getnext"))
  90. operation = GETNEXT;
  91. else if (!strcmp(*argumentVector, "walk"))
  92. operation = WALK;
  93. else if (!strcmp(*argumentVector, "trap"))
  94. operation = TRAP;
  95. else
  96. {
  97. printf("Error: Invalid operation, '%s', specified.\n",
  98. *argumentVector);
  99. return 1;
  100. }
  101. if (operation != TRAP)
  102. {
  103. if (argumentCount < 4)
  104. {
  105. printf("Error: Incorrect number of arguments specified.\n");
  106. printf(
  107. "\nusage: snmputil [get|getnext|walk] agent community oid [oid ...]\n");
  108. printf(
  109. " snmputil trap\n");
  110. return 1;
  111. }
  112. // Get agent address...
  113. argumentVector++;
  114. argumentCount--;
  115. agent = (LPSTR)SnmpUtilMemAlloc(strlen(*argumentVector) + 1);
  116. if (agent != NULL)
  117. strcpy(agent, *argumentVector);
  118. else
  119. {
  120. printf("Error: SnmpUtilMemAlloc failed to allocate memory.\n");
  121. return 1;
  122. }
  123. // Get agent community...
  124. argumentVector++;
  125. argumentCount--;
  126. community = (LPSTR)SnmpUtilMemAlloc(strlen(*argumentVector) + 1);
  127. if (community != NULL)
  128. strcpy(community, *argumentVector);
  129. else
  130. {
  131. printf("Error: SnmpUtilMemAlloc failed to allocate memory.\n");
  132. SnmpUtilMemFree(agent);
  133. return 1;
  134. }
  135. // Get oid's...
  136. variableBindings.list = NULL;
  137. variableBindings.len = 0;
  138. while(--argumentCount)
  139. {
  140. AsnObjectIdentifier reqObject;
  141. RFC1157VarBind * tmpVb;
  142. argumentVector++;
  143. // Convert the string representation to an internal representation.
  144. if (!SnmpMgrStrToOid(*argumentVector, &reqObject))
  145. {
  146. printf("Error: Invalid oid, %s, specified.\n", *argumentVector);
  147. SnmpUtilMemFree(agent);
  148. SnmpUtilMemFree(community);
  149. SnmpUtilVarBindListFree(&variableBindings);
  150. return 1;
  151. }
  152. else
  153. {
  154. // Since sucessfull, add to the variable bindings list.
  155. variableBindings.len++;
  156. if ((tmpVb = (RFC1157VarBind *)SnmpUtilMemReAlloc(
  157. variableBindings.list, sizeof(RFC1157VarBind) *
  158. variableBindings.len)) == NULL)
  159. {
  160. printf("Error: Error allocating oid, %s.\n",
  161. *argumentVector);
  162. SnmpUtilMemFree(agent);
  163. SnmpUtilMemFree(community);
  164. SnmpUtilOidFree(&reqObject);
  165. variableBindings.len--;
  166. SnmpUtilVarBindListFree(&variableBindings);
  167. return 1;
  168. }
  169. variableBindings.list = tmpVb;
  170. variableBindings.list[variableBindings.len - 1].name =
  171. reqObject; // NOTE! structure copy
  172. variableBindings.list[variableBindings.len - 1].value.asnType =
  173. ASN_NULL;
  174. }
  175. } // end while()
  176. // Establish a SNMP session to communicate with the remote agent. The
  177. // community, communications timeout, and communications retry count
  178. // for the session are also required.
  179. if ((session = SnmpMgrOpen(agent, community, timeout, retries)) == NULL)
  180. {
  181. printf("error on SnmpMgrOpen %d\n", GetLastError());
  182. SnmpUtilMemFree(agent);
  183. SnmpUtilMemFree(community);
  184. SnmpUtilVarBindListFree(&variableBindings);
  185. return 1;
  186. }
  187. } // end if(TRAP)
  188. // Determine and perform the requested operation.
  189. if (operation == GET || operation == GETNEXT)
  190. {
  191. // Get and GetNext are relatively simple operations to perform.
  192. // Simply initiate the request and process the result and/or
  193. // possible error conditions.
  194. if (operation == GET)
  195. requestType = ASN_RFC1157_GETREQUEST;
  196. else
  197. requestType = ASN_RFC1157_GETNEXTREQUEST;
  198. // Request that the API carry out the desired operation.
  199. if (!SnmpMgrRequest(session, requestType, &variableBindings,
  200. &errorStatus, &errorIndex))
  201. {
  202. // The API is indicating an error.
  203. printf("error on SnmpMgrRequest %d\n", GetLastError());
  204. }
  205. else
  206. {
  207. // The API succeeded, errors may be indicated from the remote
  208. // agent.
  209. if (errorStatus > 0)
  210. {
  211. printf("Error: errorStatus=%d, errorIndex=%d\n",
  212. errorStatus, errorIndex);
  213. }
  214. else
  215. {
  216. // Display the resulting variable bindings.
  217. UINT i;
  218. char *string = NULL;
  219. for(i=0; i < variableBindings.len; i++)
  220. {
  221. SnmpMgrOidToStr(&variableBindings.list[i].name, &string);
  222. printf("Variable = %s\n", string);
  223. if (string) SnmpUtilMemFree(string);
  224. printf("Value = ");
  225. SnmpUtilPrintAsnAny(&variableBindings.list[i].value);
  226. printf("\n");
  227. } // end for()
  228. }
  229. }
  230. // Free allocated memory.
  231. SnmpUtilMemFree(agent);
  232. SnmpUtilMemFree(community);
  233. SnmpUtilVarBindListFree(&variableBindings);
  234. }
  235. else if (operation == WALK)
  236. {
  237. // Walk is a common term used to indicate that all MIB variables
  238. // under a given OID are to be traversed and displayed. This is
  239. // a more complex operation requiring tests and looping in addition
  240. // to the steps for get/getnext above.
  241. UINT i;
  242. UINT j;
  243. AsnObjectIdentifier *rootOidList = NULL;
  244. UINT rootOidLen = 0;
  245. UINT *rootOidXlat = NULL;
  246. rootOidLen = variableBindings.len;
  247. rootOidList = (AsnObjectIdentifier*)SnmpUtilMemAlloc(rootOidLen *
  248. sizeof(AsnObjectIdentifier));
  249. rootOidXlat = (UINT *)SnmpUtilMemAlloc(rootOidLen * sizeof(UINT));
  250. for (i=0; i < rootOidLen; i++)
  251. {
  252. SnmpUtilOidCpy(&rootOidList[i], &variableBindings.list[i].name);
  253. rootOidXlat[i] = i;
  254. }
  255. requestType = ASN_RFC1157_GETNEXTREQUEST;
  256. while(1)
  257. {
  258. if (!SnmpMgrRequest(session, requestType, &variableBindings,
  259. &errorStatus, &errorIndex))
  260. {
  261. // The API is indicating an error.
  262. printf("error on SnmpMgrRequest %d\n", GetLastError());
  263. break;
  264. }
  265. else
  266. {
  267. // The API succeeded, errors may be indicated from the remote
  268. // agent.
  269. char *string = NULL;
  270. UINT nBindingsLeft = variableBindings.len;
  271. UINT nSubTreesDone = 0;
  272. RFC1157VarBind *tempVarBindList;
  273. BOOL fGotoExit = FALSE;
  274. if (errorStatus == SNMP_ERRORSTATUS_NOERROR)
  275. {
  276. // Test for end of subtree or end of MIB.
  277. for(i=0; i < nBindingsLeft; i++)
  278. {
  279. // obtain root
  280. j = rootOidXlat[i];
  281. if (SnmpUtilOidNCmp(&variableBindings.list[i].name,
  282. &rootOidList[j], rootOidList[j].idLength))
  283. {
  284. nSubTreesDone++;
  285. rootOidXlat[i] = 0xffffffff;
  286. }
  287. else
  288. {
  289. SnmpMgrOidToStr(&variableBindings.list[i].name, &string);
  290. printf("Variable = %s\n", string);
  291. if (string) SnmpUtilMemFree(string);
  292. printf("Value = ");
  293. SnmpUtilPrintAsnAny(&variableBindings.list[i].value);
  294. printf("\n");
  295. }
  296. AsnValueFree(&variableBindings.list[i].value);
  297. }
  298. if (nBindingsLeft > 1)
  299. {
  300. printf("\n"); // separate table entries
  301. }
  302. }
  303. else if (errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME)
  304. {
  305. if (!(errorIndex && (errorIndex <= (INT)nBindingsLeft)))
  306. {
  307. errorIndex = 1; // invalidate first variable
  308. }
  309. nSubTreesDone++;
  310. rootOidXlat[errorIndex-1] = 0xffffffff;
  311. errorStatus = 0;
  312. errorIndex = 0;
  313. }
  314. else
  315. {
  316. printf("Error: errorStatus=%d, errorIndex=%d \n",
  317. errorStatus, errorIndex);
  318. break;
  319. }
  320. // Test to see if any or all subtrees walked
  321. if (nSubTreesDone == 0)
  322. {
  323. continue;
  324. }
  325. else if (nSubTreesDone >= nBindingsLeft)
  326. {
  327. printf("End of MIB subtree.\n\n");
  328. break;
  329. }
  330. // Fixup variable list
  331. tempVarBindList = variableBindings.list;
  332. variableBindings.len = nBindingsLeft - nSubTreesDone;
  333. variableBindings.list = (RFC1157VarBind *)SnmpUtilMemAlloc(
  334. variableBindings.len * sizeof(RFC1157VarBind));
  335. if (variableBindings.list == NULL)
  336. {
  337. printf("Error: failed to allocate a new varbind list.\n");
  338. // undo the changes
  339. variableBindings.list = tempVarBindList;
  340. variableBindings.len = nBindingsLeft;
  341. break;
  342. }
  343. for(i=0, j=0; i < nBindingsLeft; i++)
  344. {
  345. if ((rootOidXlat[i] != 0xffffffff) &&
  346. (j < variableBindings.len))
  347. {
  348. if (!SnmpUtilVarBindCpy(
  349. &variableBindings.list[j],
  350. &tempVarBindList[i]
  351. ))
  352. {
  353. printf("Error: SnmpUtilVarBindCpy failed.\n");
  354. // erase itermediate results and undo the changes
  355. SnmpUtilVarBindListFree(&variableBindings);
  356. variableBindings.list = tempVarBindList;
  357. variableBindings.len = nBindingsLeft;
  358. tempVarBindList = NULL; // ownership transferred
  359. fGotoExit = TRUE;
  360. break;
  361. }
  362. rootOidXlat[j++] = rootOidXlat[i];
  363. }
  364. SnmpUtilVarBindFree(
  365. &tempVarBindList[i]
  366. );
  367. }
  368. if (fGotoExit)
  369. {
  370. // break out the while loop
  371. break;
  372. }
  373. SnmpUtilMemFree(tempVarBindList);
  374. } // end if()
  375. } // end while()
  376. // Free allocated memory.
  377. SnmpUtilMemFree(agent);
  378. SnmpUtilMemFree(community);
  379. SnmpUtilMemFree(rootOidXlat);
  380. SnmpUtilVarBindListFree(&variableBindings);
  381. for (i=0; i < rootOidLen; i++)
  382. {
  383. SnmpUtilOidFree(&rootOidList[i]);
  384. }
  385. SnmpUtilMemFree(rootOidList);
  386. }
  387. else if (operation == TRAP)
  388. {
  389. // Trap handling can be done two different ways: event driven or
  390. // polled. The following code illustrates the steps to use event
  391. // driven trap reception in a management application.
  392. HANDLE hNewTraps = NULL;
  393. if (!SnmpMgrTrapListen(&hNewTraps))
  394. {
  395. printf("error on SnmpMgrTrapListen %d\n", GetLastError());
  396. return 1;
  397. }
  398. else
  399. {
  400. printf("snmputil: listening for traps...\n");
  401. }
  402. while(1)
  403. {
  404. DWORD dwResult;
  405. if ((dwResult = WaitForSingleObject(hNewTraps, 0xffffffff))
  406. == 0xffffffff)
  407. {
  408. printf("error on WaitForSingleObject %d\n",
  409. GetLastError());
  410. }
  411. else if (!ResetEvent(hNewTraps))
  412. {
  413. printf("error on ResetEvent %d\n", GetLastError());
  414. }
  415. else
  416. {
  417. AsnObjectIdentifier enterprise;
  418. AsnNetworkAddress agentAddress;
  419. AsnNetworkAddress sourceAddress;
  420. AsnInteger genericTrap;
  421. AsnInteger specificTrap;
  422. AsnOctetString community;
  423. AsnTimeticks timeStamp;
  424. RFC1157VarBindList variableBindings;
  425. UINT i;
  426. char *string = NULL;
  427. while(SnmpMgrGetTrapEx(
  428. &enterprise,
  429. &agentAddress,
  430. &sourceAddress,
  431. &genericTrap,
  432. &specificTrap,
  433. &community,
  434. &timeStamp,
  435. &variableBindings))
  436. {
  437. printf("Incoming Trap:\n"
  438. " generic = %d\n"
  439. " specific = %d\n"
  440. " timeStamp = %u\n",
  441. genericTrap,
  442. specificTrap,
  443. timeStamp);
  444. SnmpMgrOidToStr(&enterprise, &string);
  445. printf (" enterprise = %s\n", string);
  446. if (string)
  447. SnmpUtilMemFree(string);
  448. SnmpUtilOidFree(&enterprise);
  449. if (agentAddress.length == 4) {
  450. printf (" agent = %d.%d.%d.%d\n",
  451. (int)agentAddress.stream[0],
  452. (int)agentAddress.stream[1],
  453. (int)agentAddress.stream[2],
  454. (int)agentAddress.stream[3]);
  455. }
  456. if (agentAddress.dynamic) {
  457. SnmpUtilMemFree(agentAddress.stream);
  458. }
  459. if (sourceAddress.length == 4) {
  460. printf (" source IP = %d.%d.%d.%d\n",
  461. (int)sourceAddress.stream[0],
  462. (int)sourceAddress.stream[1],
  463. (int)sourceAddress.stream[2],
  464. (int)sourceAddress.stream[3]);
  465. }
  466. else if (sourceAddress.length == 10) {
  467. printf (" source IPX = %.2x%.2x%.2x%.2x."
  468. "%.2x%.2x%.2x%.2x%.2x%.2x\n",
  469. (int)sourceAddress.stream[0],
  470. (int)sourceAddress.stream[1],
  471. (int)sourceAddress.stream[2],
  472. (int)sourceAddress.stream[3],
  473. (int)sourceAddress.stream[4],
  474. (int)sourceAddress.stream[5],
  475. (int)sourceAddress.stream[6],
  476. (int)sourceAddress.stream[7],
  477. (int)sourceAddress.stream[8],
  478. (int)sourceAddress.stream[9]);
  479. }
  480. if (sourceAddress.dynamic) {
  481. SnmpUtilMemFree(sourceAddress.stream);
  482. }
  483. if (community.length)
  484. {
  485. string = SnmpUtilMemAlloc (community.length + 1);
  486. memcpy (string, community.stream, community.length);
  487. string[community.length] = '\0';
  488. printf (" community = %s\n", string);
  489. SnmpUtilMemFree(string);
  490. }
  491. if (community.dynamic) {
  492. SnmpUtilMemFree(community.stream);
  493. }
  494. for(i=0; i < variableBindings.len; i++)
  495. {
  496. SnmpMgrOidToStr(&variableBindings.list[i].name, &string);
  497. printf(" variable = %s\n", string);
  498. if (string) SnmpUtilMemFree(string);
  499. printf(" value = ");
  500. SnmpUtilPrintAsnAny(&variableBindings.list[i].value);
  501. } // end for()
  502. printf("\n");
  503. SnmpUtilVarBindListFree(&variableBindings);
  504. }
  505. dwResult = GetLastError(); // check for errors...
  506. if ((dwResult != NOERROR) && (dwResult != SNMP_MGMTAPI_NOTRAPS))
  507. {
  508. printf("error on SnmpMgrGetTrap %d\n", dwResult);
  509. }
  510. }
  511. } // end while()
  512. } // end if(operation)
  513. if (operation != TRAP)
  514. {
  515. // Close SNMP session with the remote agent.
  516. if (!SnmpMgrClose(session))
  517. {
  518. printf("error on SnmpMgrClose %d\n", GetLastError());
  519. return 1;
  520. }
  521. }
  522. // Let the command interpreter know things went ok.
  523. return 0;
  524. } // end main()