snmpWalkThreads.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*_############################################################################
  2. _##
  3. _## snmpWalkThreads.cpp
  4. _##
  5. _## SNMP++v3.2.23
  6. _## -----------------------------------------------
  7. _## Copyright (c) 2001-2007 Jochen Katz, Frank Fock
  8. _##
  9. _## This software is based on SNMP++2.6 from Hewlett Packard:
  10. _##
  11. _## Copyright (c) 1996
  12. _## Hewlett-Packard Company
  13. _##
  14. _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  15. _## Permission to use, copy, modify, distribute and/or sell this software
  16. _## and/or its documentation is hereby granted without fee. User agrees
  17. _## to display the above copyright notice and this license notice in all
  18. _## copies of the software and any documentation of the software. User
  19. _## agrees to assume all liability for the use of the software;
  20. _## Hewlett-Packard and Jochen Katz make no representations about the
  21. _## suitability of this software for any purpose. It is provided
  22. _## "AS-IS" without warranty of any kind, either express or implied. User
  23. _## hereby grants a royalty-free license to any and all derivatives based
  24. _## upon this software code base.
  25. _##
  26. _## Stuttgart, Germany, Sun Nov 11 15:10:59 CET 2007
  27. _##
  28. _##########################################################################*/
  29. /*
  30. snmpWalk.cpp
  31. Copyright (c) 1996
  32. Hewlett-Packard Company
  33. ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  34. Permission to use, copy, modify, distribute and/or sell this software
  35. and/or its documentation is hereby granted without fee. User agrees
  36. to display the above copyright notice and this license notice in all
  37. copies of the software and any documentation of the software. User
  38. agrees to assume all liability for the use of the software; Hewlett-Packard
  39. makes no representations about the suitability of this software for any
  40. purpose. It is provided "AS-IS" without warranty of any kind,either express
  41. or implied. User hereby grants a royalty-free license to any and all
  42. derivatives based upon this software code base.
  43. Peter E. Mellquist
  44. */
  45. char snmpwalkthreads_cpp_version[]="@(#) SNMP++ $Id: snmpWalkThreads.cpp 264 2006-06-16 20:53:15Z fock $";
  46. #include "snmp_pp/snmp_pp.h"
  47. #include "snmp_pp/reentrant.h"
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #ifdef SNMP_PP_NAMESPACE
  51. using namespace Snmp_pp;
  52. #endif
  53. #if (__GNUC__ > 2)
  54. #include <iostream>
  55. using std::cerr;
  56. using std::cout;
  57. using std::endl;
  58. using std::flush;
  59. #else
  60. #include <iostream.h>
  61. #endif
  62. #ifdef _THREADS
  63. static pthread_attr_t* attr = 0;
  64. #ifdef _WIN32THREADS
  65. #error "This example is not available on WIN32 platforms!"
  66. #endif
  67. #endif
  68. UdpAddress address[1000];
  69. Snmp* snmp = 0;
  70. snmp_version version=version1; // default is v1
  71. int retries=1; // default retries is 1
  72. int timeout=100; // default is 1 second
  73. u_short port=161; // default snmp port is 161
  74. OctetStr community("public"); // read community
  75. #ifdef _SNMPv3
  76. OctetStr privPassword("");
  77. OctetStr authPassword("");
  78. OctetStr securityName("");
  79. int securityModel = SecurityModel_USM;
  80. int securityLevel = SecurityLevel_authPriv;
  81. OctetStr contextName("");
  82. OctetStr contextEngineID("");
  83. long authProtocol = SNMPv3_usmNoAuthProtocol;
  84. long privProtocol = SNMPv3_usmNoPrivProtocol;
  85. #endif
  86. #define BULK_MAX 10
  87. SnmpSynchronized ssync;
  88. void* runable(void *data) {
  89. //--------[ build up SNMP++ object needed ]-------------------------------
  90. ssync.lock();
  91. printf("HELLO:%s\n", community.get_printable());
  92. int t = *((int*)data);
  93. Pdu pdu; // construct a Pdu object
  94. Vb vb; // construct a Vb object
  95. vb.set_oid("1"); // set the Oid portion of the Vb
  96. pdu += vb; // add the vb to the Pdu
  97. CTarget ctarget(address[t]); // make a target using the address
  98. #ifdef _SNMPv3
  99. UTarget utarget(address[t]);
  100. if (version == version3) {
  101. utarget.set_version( version); // set the SNMP version SNMPV1 or V2 or V3
  102. utarget.set_retry( retries); // set the number of auto retries
  103. utarget.set_timeout( timeout); // set timeout
  104. utarget.set_security_model( securityModel);
  105. utarget.set_security_name( securityName);
  106. pdu.set_security_level( securityLevel);
  107. pdu.set_context_name (contextName);
  108. pdu.set_context_engine_id(contextEngineID);
  109. }
  110. else {
  111. #endif
  112. ctarget.set_version( version); // set the SNMP version SNMPV1 or V2 or V3
  113. ctarget.set_retry( retries); // set the number of auto retries
  114. ctarget.set_timeout( timeout); // set timeout
  115. ctarget.set_readcommunity( community); // set the read community to use
  116. ctarget.set_writecommunity( community);
  117. #ifdef _SNMPv3
  118. }
  119. #endif
  120. //-------[ issue the request, blocked mode ]-----------------------------
  121. cout << "(" << t << "): "
  122. << "SNMP++ snmpWalk to " << address[t].get_printable() << " SNMPV"
  123. #ifdef _SNMPv3
  124. << ((version==version3) ? (version) : (version+1))
  125. #else
  126. << (version+1)
  127. #endif
  128. << " Retries=" << retries
  129. << " Timeout=" << timeout * 10 <<"ms";
  130. #ifdef _SNMPv3
  131. if (version == version3)
  132. cout << endl
  133. << "securityName= " << securityName.get_printable()
  134. << ", securityLevel= " << securityLevel
  135. << ", securityModel= " << securityModel << endl
  136. << "contextName= " << contextName.get_printable()
  137. << ", contextEngineID= " << contextEngineID.get_printable()
  138. << endl;
  139. else
  140. #endif
  141. cout << " Community=" << community.get_printable() << endl << flush;
  142. SnmpTarget *target;
  143. #ifdef _SNMPv3
  144. if (version == version3)
  145. target = &utarget;
  146. else
  147. #endif
  148. target = &ctarget;
  149. int status = 0;
  150. int requests = 0;
  151. int objects = 0;
  152. ssync.unlock();
  153. while (( status = snmp->get_bulk( pdu,*target,0,BULK_MAX))
  154. == SNMP_CLASS_SUCCESS)
  155. {
  156. requests++;
  157. ssync.lock();
  158. for ( int z=0;z<pdu.get_vb_count(); z++) {
  159. pdu.get_vb( vb,z);
  160. #ifdef _SNMPv3
  161. if (pdu.get_type() == REPORT_MSG) {
  162. Oid tmp;
  163. vb.get_oid(tmp);
  164. cout << "(" << t << "): " << "Received a reportPdu: "
  165. << snmp->error_msg( tmp)
  166. << endl
  167. << vb.get_printable_oid() << " = "
  168. << vb.get_printable_value() << endl;
  169. ssync.unlock();
  170. return 0;
  171. }
  172. #endif
  173. objects++;
  174. // look for var bind exception, applies to v2 only
  175. if ( vb.get_syntax() != sNMP_SYNTAX_ENDOFMIBVIEW) {
  176. cout << "(" << t << "): "
  177. << vb.get_printable_oid() << " = ";
  178. cout << vb.get_printable_value() << "\n";
  179. }
  180. else {
  181. cout << "(" << t << "): "
  182. << "End of MIB Reached\n";
  183. cout << "(" << t << "): "
  184. << "Total # of Requests = " << requests << "\n";
  185. cout << "(" << t << "): "
  186. << "Total # of Objects = " << objects << "\n";
  187. ssync.unlock();
  188. return 0;
  189. }
  190. }
  191. ssync.unlock();
  192. // last vb becomes seed of next rquest
  193. pdu.set_vblist(&vb, 1);
  194. }
  195. if ( status != SNMP_ERROR_NO_SUCH_NAME)
  196. cout << "(" << t << "): "
  197. << "SNMP++ snmpWalk Error, " << snmp->error_msg( status) << "\n";
  198. cout << "(" << t << "): "
  199. << "Total # of Requests = " << requests << "\n";
  200. cout << "(" << t << "): "
  201. << "Total # of Objects = " << objects << "\n";
  202. return 0;
  203. } // end Walk
  204. int main(int argc, char **argv)
  205. {
  206. //---------[ check the arg count ]----------------------------------------
  207. if ( argc < 2) {
  208. cout << "Usage:\n";
  209. cout << "snmpWalkThreads host/port [host/port]... [options]\n";
  210. cout << "StartOid: 1\n";
  211. cout << "options: -vN , use SNMP version 1, 2 or 3, default is 1\n";
  212. cout << " -PPort , remote port to use\n";
  213. cout << " -CCommunity_name, specify community default is 'public' \n";
  214. cout << " -rN , retries default is N = 1 retry\n";
  215. cout << " -tN , timeout in hundredths of seconds; default is N = 100\n";
  216. #ifdef _SNMPv3
  217. cout << " -snSecurityName, " << endl;
  218. cout << " -slN , securityLevel to use, default N = 3 = authPriv" << endl;
  219. cout << " -smN , securityModel to use, only default N = 3 = USM possible\n";
  220. cout << " -cnContextName, default empty string" << endl;
  221. cout << " -ceContextEngineID, as hex e.g. 800007E580, default empty string" << endl;
  222. cout << " -authPROT, use authentication protocol NONE, SHA or MD5\n";
  223. cout << " -privPROT, use privacy protocol NONE, DES, 3DESEDE, IDEA, AES128, AES192 or AES256\n";
  224. cout << " -uaAuthPassword\n";
  225. cout << " -upPrivPassword\n";
  226. #endif
  227. return 0;
  228. }
  229. Snmp::socket_startup(); // Initialize socket subsystem
  230. //---------[ make a GenAddress and Oid object to retrieve ]---------------
  231. address[0] = UdpAddress(argv[1]);
  232. if ( !address[0].valid()) { // check validity of address
  233. cout << "Invalid Address or DNS Name, " << argv[1] << "\n";
  234. return -1;
  235. }
  236. int x=2;
  237. while ((x<argc) && (x<100) && (strstr(argv[x],"-")==0)) {
  238. address[x-1] = UdpAddress(argv[x]);
  239. if ( !address[x-1].valid()) { // check validity of address
  240. cout << "Invalid Address or DNS Name, " << argv[x] << "\n";
  241. return -1;
  242. }
  243. x++;
  244. }
  245. int threads = x-1;
  246. cout << community.get_printable() << endl;
  247. //---------[ determine options to use ]-----------------------------------
  248. char *ptr;
  249. for(;x<argc;x++) { // parse for version
  250. if ( strstr( argv[x],"-v2")!= 0) {
  251. version = version2c;
  252. continue;
  253. }
  254. if ( strstr( argv[x],"-r")!= 0) { // parse for retries
  255. ptr = argv[x]; ptr++; ptr++;
  256. retries = atoi(ptr);
  257. if (( retries<0)|| (retries>5)) retries=1;
  258. continue;
  259. }
  260. if ( strstr( argv[x], "-t")!=0) { // parse for timeout
  261. ptr = argv[x]; ptr++; ptr++;
  262. timeout = atoi( ptr);
  263. if (( timeout < 100)||( timeout>500)) timeout=100;
  264. continue;
  265. }
  266. if ( strstr( argv[x],"-C")!=0) {
  267. ptr = argv[x]; ptr++; ptr++;
  268. community = ptr;
  269. continue;
  270. }
  271. if ( strstr( argv[x],"-P")!=0) {
  272. ptr = argv[x]; ptr++; ptr++;
  273. sscanf(ptr, "%hu", &port);
  274. continue;
  275. }
  276. #ifdef _SNMPv3
  277. if ( strstr( argv[x],"-v3")!= 0) {
  278. version = version3;
  279. continue;
  280. }
  281. if ( strstr( argv[x],"-auth") != 0) {
  282. ptr = argv[x]; ptr+=5;
  283. if (strcasecmp(ptr, "SHA") == 0)
  284. authProtocol = SNMP_AUTHPROTOCOL_HMACSHA;
  285. else if (strcasecmp(ptr, "MD5") == 0)
  286. authProtocol = SNMP_AUTHPROTOCOL_HMACMD5;
  287. else
  288. authProtocol = SNMP_AUTHPROTOCOL_NONE;
  289. continue;
  290. }
  291. if ( strstr( argv[x],"-priv") != 0) {
  292. ptr = argv[x]; ptr+=5;
  293. if (strcasecmp(ptr, "DES") == 0)
  294. privProtocol = SNMP_PRIVPROTOCOL_DES;
  295. else if (strcasecmp(ptr, "3DESEDE") == 0)
  296. privProtocol = SNMP_PRIVPROTOCOL_3DESEDE;
  297. else if (strcasecmp(ptr, "IDEA") == 0)
  298. privProtocol = SNMP_PRIVPROTOCOL_IDEA;
  299. else if (strcasecmp(ptr, "AES128") == 0)
  300. privProtocol = SNMP_PRIVPROTOCOL_AES128;
  301. else if (strcasecmp(ptr, "AES192") == 0)
  302. privProtocol = SNMP_PRIVPROTOCOL_AES192;
  303. else if (strcasecmp(ptr, "AES256") == 0)
  304. privProtocol = SNMP_PRIVPROTOCOL_AES256;
  305. else
  306. privProtocol = SNMP_PRIVPROTOCOL_NONE;
  307. printf("\n\nPrivProt : %ld\n", privProtocol);
  308. continue;
  309. }
  310. if ( strstr( argv[x],"-sn")!=0) {
  311. ptr = argv[x]; ptr+=3;
  312. securityName = ptr;
  313. continue;
  314. }
  315. if ( strstr( argv[x], "-sl")!=0) {
  316. ptr = argv[x]; ptr+=3;
  317. securityLevel = atoi( ptr);
  318. if (( securityLevel < SecurityLevel_noAuthNoPriv) ||
  319. ( securityLevel > SecurityLevel_authPriv))
  320. securityLevel = SecurityLevel_authPriv;
  321. continue;
  322. }
  323. if ( strstr( argv[x], "-sm")!=0) {
  324. ptr = argv[x]; ptr+=3;
  325. securityModel = atoi( ptr);
  326. if (( securityModel < SecurityModel_v1) ||
  327. ( securityModel > SecurityModel_USM))
  328. securityModel = SecurityModel_USM;
  329. continue;
  330. }
  331. if ( strstr( argv[x],"-cn")!=0) {
  332. ptr = argv[x]; ptr+=3;
  333. contextName = ptr;
  334. continue;
  335. }
  336. if ( strstr( argv[x],"-ce")!=0) {
  337. ptr = argv[x]; ptr+=3;
  338. contextEngineID = OctetStr::from_hex_string(ptr);
  339. continue;
  340. }
  341. if ( strstr( argv[x],"-ua")!=0) {
  342. ptr = argv[x]; ptr+=3;
  343. authPassword = ptr;
  344. continue;
  345. }
  346. if ( strstr( argv[x],"-up")!=0) {
  347. ptr = argv[x]; ptr+=3;
  348. privPassword = ptr;
  349. continue;
  350. }
  351. #endif
  352. }
  353. //----------[ create a SNMP++ session ]-----------------------------------
  354. int status;
  355. // bind to any port and use IPv6 if enabled
  356. #ifdef SNMP_PP_IPv6
  357. snmp = new Snmp(status, 0, true);
  358. #else
  359. snmp = new Snmp(status);
  360. #endif
  361. if ( status != SNMP_CLASS_SUCCESS) {
  362. cout << "SNMP++ Session Create Fail, "
  363. << snmp->error_msg(status) << "\n";
  364. return -3;
  365. }
  366. #ifdef _SNMPv3
  367. //---------[ init SnmpV3 ]--------------------------------------------
  368. v3MP *v3_MP;
  369. if (version == version3) {
  370. char *engineId = "snmpWalk";
  371. char *filename = "snmpv3_boot_counter";
  372. unsigned int snmpEngineBoots = 0;
  373. int status;
  374. status = getBootCounter(filename, engineId, snmpEngineBoots);
  375. if ((status != SNMPv3_OK) && (status < SNMPv3_FILEOPEN_ERROR))
  376. {
  377. cout << "Error loading snmpEngineBoots counter: " << status << endl;
  378. return 1;
  379. }
  380. snmpEngineBoots++;
  381. status = saveBootCounter(filename, engineId, snmpEngineBoots);
  382. if (status != SNMPv3_OK)
  383. {
  384. cout << "Error saving snmpEngineBoots counter: " << status << endl;
  385. return 1;
  386. }
  387. int construct_status;
  388. v3_MP = new v3MP(engineId, snmpEngineBoots, construct_status);
  389. USM *usm = v3_MP->get_usm();
  390. usm->add_usm_user(securityName,
  391. authProtocol, privProtocol,
  392. authPassword, privPassword);
  393. }
  394. else
  395. {
  396. // MUST create a dummy v3MP object if _SNMPv3 is enabled!
  397. int construct_status;
  398. v3_MP = new v3MP("dummy", 0, construct_status);
  399. }
  400. #endif
  401. #ifdef _THREADS
  402. pthread_t thread[100];
  403. int started = threads;
  404. #endif
  405. while (threads) {
  406. #ifdef _THREADS
  407. if (!attr) {
  408. attr = new pthread_attr_t;
  409. pthread_attr_init(attr);
  410. pthread_attr_setdetachstate(attr, PTHREAD_CREATE_JOINABLE);
  411. }
  412. pthread_create(&thread[threads-1], 0,
  413. &runable,
  414. (void*)new int(threads-1));
  415. #else
  416. int n = threads - 1;
  417. runable(&n);
  418. #endif
  419. threads--;
  420. }
  421. #ifdef _THREADS
  422. // wait for threads to terminate
  423. for (int i=0; i<started; i++) {
  424. cout << "JOINING THREAD " << i << endl;
  425. pthread_join(thread[i], 0);
  426. }
  427. #endif
  428. cout << "END" << endl;
  429. Snmp::socket_cleanup(); // Shut down socket subsystem
  430. }