MainWindow.cpp
上传用户:cnryan
上传日期:2008-12-15
资源大小:260k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*_############################################################################
  2.   _## 
  3.   _##  MainWindow.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.21
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2006 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, Fri Jun 16 17:48:57 CEST 2006 
  27.   _##  
  28.   _##########################################################################*/
  29. #ifndef _MSC_VER
  30. #include <unistd.h>
  31. #endif
  32. #include <iostream>
  33. #include <qstring.h>
  34. #include <qlineedit.h>
  35. #include <qmessagebox.h>
  36. #include <qtimer.h>
  37. #include <qtextedit.h>
  38. #include <qpushbutton.h>
  39. #include <qcombobox.h>
  40. #include <qspinbox.h>
  41. #include <qradiobutton.h>
  42. #include <MainWindow.h>
  43. #include <Properties.h>
  44. #include "snmp_pp/snmp_pp.h"
  45. #include "snmp_pp/notifyqueue.h"
  46. #include "snmp_pp/log.h"
  47. using std::cout;
  48. using std::cerr;
  49. using std::endl;
  50. #define FILE_USERS "usm_users.bin"
  51. #define FILE_LOCALIZED_USERS "usm_localized_users.bin"
  52. /// C Callback function for snmp++
  53. void callback(int reason, Snmp *snmp, Pdu &pdu, SnmpTarget &target, void *cd)
  54. {
  55.   if (cd)
  56.   {
  57.     // just call the real callback member function...
  58.     ((MainWindow*)cd)->async_callback(reason, snmp, pdu, target);
  59.   }
  60. }
  61. void MainWindow::async_callback(int reason, Snmp * /*snmp*/, Pdu &pdu,
  62. SnmpTarget &target)
  63. {
  64.   Vb nextVb;
  65.   int pdu_error;
  66.   QString prefix_text;
  67.   QString notify_text;
  68.   push_button_get_next->setEnabled(true);
  69.   // What is the reason for this callback?
  70.   if (reason == SNMP_CLASS_NOTIFICATION)
  71.   {
  72.     prefix_text = "Trap:    ";
  73.     // get the notify id for traps
  74.     Oid id;
  75.     pdu.get_notify_id(id);
  76.     notify_text = QString(" ID: %1 Type %2 -- ").arg(id.get_printable())
  77.                   .arg(pdu.get_type());
  78.   }
  79.   else if (reason == SNMP_CLASS_ASYNC_RESPONSE)
  80.   {
  81.     prefix_text = "Response ";
  82.   }
  83.   else if (reason == SNMP_CLASS_TIMEOUT)
  84.   {
  85.     prefix_text = "Timeout  ";
  86.   }
  87.   else
  88.   {
  89.     QString err = QString("nDid not receive async response/trap: (%1) %2n")
  90.                   .arg(reason).arg(Snmp::error_msg(reason));
  91.     text_edit_output->append(err);
  92.   }
  93.   // Look at the error status of the Pdu
  94.   pdu_error = pdu.get_error_status();
  95.   if (pdu_error)
  96.   {
  97.     QString err = "nResponse contains error:n";
  98.     err += Snmp::error_msg(pdu_error);
  99.     text_edit_output->append(err);
  100.     return;
  101.   }
  102.   // The Pdu must contain at least one Vb
  103.   if (pdu.get_vb_count() == 0)
  104.   {
  105.     QString err = "nPdu is emptyn";
  106.     text_edit_output->append(err);
  107.     return;
  108.   }
  109.   for (int i=0; i<pdu.get_vb_count(); i++)
  110.   {
  111.     // Get the Vb of the Pdu
  112.     pdu.get_vb(nextVb, i);
  113.     // Get Oid and value from the Vb and display it
  114.     line_edit_obj_id->setText(nextVb.get_printable_oid());
  115.     line_edit_value->setText(nextVb.get_printable_value());
  116.     text_edit_output->append(prefix_text +
  117.      target.get_address().get_printable() +
  118.      " -- " +
  119.      notify_text +
  120.      line_edit_obj_id->text() + " = " +
  121.      line_edit_value->text() + "n");
  122.   }
  123.   // If we received a inform pdu, we have to send a response
  124.   if (pdu.get_type() == sNMP_PDU_INFORM)
  125.   {
  126.     text_edit_output->append("Sending response to inform.n");
  127.     // just change the value of the first vb
  128.     pdu.get_vb(nextVb, 0);
  129.     nextVb.set_value("This is the response.");
  130.     pdu.set_vb(nextVb, 0);
  131.     snmp->response(pdu, target);
  132.   }
  133. }
  134. MainWindow::MainWindow(QWidget* parent, const char* name, WFlags fl)
  135.   : MainWindowPrivate(parent, name, fl)
  136. {
  137.   int status;
  138. #ifndef _NO_LOGGING
  139.   DefaultLog::log()->set_filter(ERROR_LOG, 5);
  140.   DefaultLog::log()->set_filter(WARNING_LOG, 5);
  141.   DefaultLog::log()->set_filter(EVENT_LOG, 5);
  142.   DefaultLog::log()->set_filter(INFO_LOG, 5);
  143.   DefaultLog::log()->set_filter(DEBUG_LOG, 8);
  144.   // Write debug info to a file
  145.   DefaultLog::init(new AgentLogImpl("QtExample.log"));
  146. #endif
  147.   Snmp::socket_startup();  // Initialize socket subsystem
  148.   connect(&timer, SIGNAL(timeout()), this, SLOT(timer_expired()));
  149.   // get the Boot counter (you may use any own method for this)
  150.   char *engineId = "not_needed";
  151.   char *filename = "snmpv3_boot_counter";
  152.   unsigned int snmpEngineBoots = 0;
  153.   status = getBootCounter(filename, engineId, snmpEngineBoots);
  154.   if ((status != SNMPv3_OK) && (status < SNMPv3_FILEOPEN_ERROR))
  155.   {
  156.     QString err = QString("Error loading snmpEngineBoots counter: %1n")
  157.                          .arg(status);
  158.     text_edit_output->append(err);
  159.   }
  160.   // increase the boot counter
  161.   snmpEngineBoots++;
  162.   // save the boot counter
  163.   status = saveBootCounter(filename, engineId, snmpEngineBoots);
  164.   if (status != SNMPv3_OK)
  165.   {
  166.     QString err = QString("Error saving snmpEngineBoots counter: %1n")
  167.                          .arg(status);
  168.     text_edit_output->append(err);
  169.   }
  170.   // Create our SNMP session object
  171.   snmp = new Snmp(status);
  172.   if (status != SNMP_CLASS_SUCCESS)
  173.   {
  174.     QString err = "nCould not create SNMP++ session:n";
  175.     err += Snmp::error_msg(status);
  176.     text_edit_output->append(err);
  177.   }
  178.   // If _SNMPv3 is enabled we MUST create ONE v3MP object!
  179.   v3mp = new v3MP(engineId, snmpEngineBoots, status);
  180.   if (status != SNMPv3_MP_OK)
  181.   {
  182.     QString err = "nCould not create v3MP object:n";
  183.     err += Snmp::error_msg(status);
  184.     text_edit_output->append(err);
  185.   }
  186.   // The v3MP creates a USM object, get the pointer to it
  187.   USM *usm = v3mp->get_usm();
  188.   // Load the USM users from a file
  189.   if (SNMPv3_USM_OK != usm->load_users(FILE_USERS))
  190.   {
  191.     QString err = "nCould not load users from file.n";
  192.     text_edit_output->append(err);
  193.   }    
  194. #if 0 // Localized users will be created automatically!
  195.   if (SNMPv3_USM_OK != usm->load_localized_users(FILE_LOCALIZED_USERS))
  196.   {
  197.     QString err = "nCould not load localized users from file.n";
  198.     text_edit_output->append(err);
  199.   }    
  200. #endif
  201.   update_combobox_sec_name();
  202. }
  203. void MainWindow::update_combobox_sec_name()
  204. {
  205.   USM *usm = v3mp->get_usm();
  206.   combo_box_sec_name->clear();
  207.   // get all security names
  208.   usm->lock_user_name_table(); // lock table for peek_XXX()
  209.   const struct UsmUserNameTableEntry *user = usm->peek_first_user();
  210.   QStringList names;
  211.   QString initial("initial");
  212.   QString to_add;
  213.   while (user)
  214.   {
  215.     to_add.setAscii((const char*)(user->usmUserSecurityName.data()),
  216.      user->usmUserSecurityName.len());
  217.     if (!names.contains(to_add) && (to_add != initial))
  218.       names += to_add;
  219.     
  220.     user = usm->peek_next_user(user);
  221.   }
  222.   usm->unlock_user_name_table(); // unlock table
  223.   combo_box_sec_name->insertStringList(names);
  224. }
  225. MainWindow::~MainWindow()
  226. {
  227.   if (snmp)
  228.   {
  229.     delete snmp;
  230.     snmp = 0;
  231.   }
  232.   if (v3mp)
  233.   {
  234.     USM *usm = v3mp->get_usm();
  235.     // Save USM users with their passwords into a file
  236.     // The passwords are not encrypted!
  237.     if (SNMPv3_USM_OK != usm->save_users(FILE_USERS))
  238.     {
  239.       QString err = "nCould not save users to file file.n";
  240.       text_edit_output->append(err);
  241.     }
  242.     
  243.     delete v3mp;
  244.     v3mp = 0;
  245.   }
  246.   Snmp::socket_cleanup();  // Shut down socket subsystem
  247. }
  248. // issue a GET-NEXT request
  249. void MainWindow::push_button_get_next_clicked()
  250. {
  251.   int status;
  252.   if (!snmp)
  253.     return;
  254.   push_button_get_next->setEnabled(false);
  255.   // Create a Oid and a address object from the entered values
  256.   Oid oid(line_edit_obj_id->text());
  257.   UdpAddress address(line_edit_target->text());
  258.   // check if the address is valid
  259.   // One problem here: if a hostname is entered, a blocking DNS lookup
  260.   // is done by the address object.
  261.   if (!address.valid())
  262.   {
  263.     QString err = QString("nInvalid Address or DNS Name: %1n")
  264.                 .arg(line_edit_target->text());
  265.     text_edit_output->append(err);
  266.     push_button_get_next->setEnabled(true);
  267.     return;
  268.   }
  269.   Pdu pdu; // empty Pdu
  270.   Vb vb;   // empty Vb
  271.   SnmpTarget *target; // will point to a CTarget(v1/v2c) or UTarget (v3)
  272.   // Set the Oid part of the Vb
  273.   vb.set_oid(oid);
  274.   // Add the Vb to the Pdu
  275.   pdu += vb;
  276.   // Get retries and timeout values
  277.   int retries = spin_box_retries->value();
  278.   int timeout = 100 * spin_box_timeout->value();
  279.   
  280.   if (radio_button_v3->isChecked())
  281.   {
  282.     // For SNMPv3 we need a UTarget object
  283.     UTarget *utarget = new UTarget(address);
  284.     utarget->set_version(version3);
  285.     utarget->set_security_model(SNMP_SECURITY_MODEL_USM);
  286.     utarget->set_security_name(combo_box_sec_name->currentText());
  287.     
  288.     target = utarget;
  289.     // set the security level to use
  290.     if (combo_box_sec_level->currentText() == "noAuthNoPriv")
  291.       pdu.set_security_level(SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV);
  292.     else if (combo_box_sec_level->currentText() == "authNoPriv")
  293.       pdu.set_security_level(SNMP_SECURITY_LEVEL_AUTH_NOPRIV);
  294.     else
  295.       pdu.set_security_level(SNMP_SECURITY_LEVEL_AUTH_PRIV);
  296.     // Not needed, as snmp++ will set it, if the user does not set it
  297.     pdu.set_context_name(line_edit_context_name->text());
  298.     pdu.set_context_engine_id(line_edit_context_engine_id->text());
  299.   }
  300.   else
  301.   {
  302.     // For SNMPv1/v2c we need a CTarget
  303.     CTarget *ctarget = new CTarget(address);
  304.     if (radio_button_v2->isChecked())
  305.       ctarget->set_version(version2c);
  306.     else
  307.       ctarget->set_version(version1);
  308.     // set the community
  309.     ctarget->set_readcommunity( line_edit_community->text());
  310.     target = ctarget;
  311.   }
  312.   target->set_retry(retries);            // set the number of auto retries
  313.   target->set_timeout(timeout);          // set timeout
  314.   // Now do an async get_next
  315.   status = snmp->get_next(pdu, *target, callback, this);
  316.   // Could we send it?
  317.   if (status == SNMP_CLASS_SUCCESS)
  318.   {
  319.     timer.start(100);
  320.   }
  321.   else
  322.   {
  323.     QString err = QString("nCould not send async GETNEXT request: %1n")
  324.                          .arg(Snmp::error_msg(status));
  325.     text_edit_output->append(err);
  326.     push_button_get_next->setEnabled(true);
  327.   }
  328.   // the target is no longer needed
  329.   delete target;
  330. }
  331. void MainWindow::timer_expired()
  332. {
  333.   // When using async requests or if we are waiting for traps or
  334.   // informs, we must call this member function periodically, as
  335.   // snmp++ does not use an internal thread.
  336.   snmp->eventListHolder->SNMPProcessPendingEvents();
  337. }
  338. // Set the properties
  339. void MainWindow::edit_properties_action_activated()
  340. {
  341.   Properties p;
  342.   p.set_snmp(snmp);
  343.   p.exec();
  344.   update_combobox_sec_name();
  345. }
  346. // Send out a SNMP Broadcast for discovery
  347. void MainWindow::push_button_broadcast_clicked()
  348. {
  349.   int status;
  350.   // Create a new SNMP session object, as while waiting for
  351.   // broadcast responses, all other responses are counted as
  352.   // broadcast responses
  353.   Snmp session(status);
  354.   if (status != SNMP_CLASS_SUCCESS)
  355.   {
  356.     QString err = "nCould not create SNMP++ session:n";
  357.     err += Snmp::error_msg(status);
  358.     text_edit_output->append(err);
  359.   }
  360.   // Create a address object from the entered value
  361.   UdpAddress address(line_edit_target->text());
  362.   // check if the address is valid
  363.   // One problem here: if a hostname is entered, a blocking DNS lookup
  364.   // is done by the address object.
  365.   if (!address.valid())
  366.   {
  367.     QString err = QString("nInvalid Address or DNS Name: %1n")
  368.                 .arg(line_edit_target->text());
  369.     text_edit_output->append(err);
  370.     return;
  371.   }
  372.   // Get retries, timeout and community
  373.   int retries = spin_box_retries->value();
  374.   int timeout = 100 * spin_box_timeout->value();
  375.   OctetStr community(line_edit_community->text());
  376.   // Get the version
  377.   snmp_version version;
  378.   if (radio_button_v3->isChecked())
  379.     version = version3;
  380.   else if (radio_button_v2->isChecked())
  381.     version = version2c;
  382.   else
  383.     version = version1;
  384.   UdpAddressCollection addresses;
  385.   // Now send the broadcast
  386.   // do multiple loops as requested from "retries"
  387.   for (int loops=1; loops<= retries + 1; ++loops)
  388.   {
  389.     status = session.broadcast_discovery(addresses,
  390.  (timeout + 99) / 100,
  391.  address, version, &community);
  392.     if (status == SNMP_CLASS_SUCCESS)
  393.     {
  394.       QString err = QString("nSuccess sending broadcast %1.n").arg(loops);
  395.       text_edit_output->append(err);
  396.     }
  397.     else
  398.     {
  399.       QString err = QString("nCould not send broadcast: %1n")
  400. .arg(Snmp::error_msg(status));
  401.       text_edit_output->append(err);
  402.     }
  403.   }
  404.   // filter out duplicates
  405.   UdpAddressCollection filtered_addrs;
  406.   int dummy_pos;
  407.   for (int n=0; n < addresses.size(); ++n)
  408.     if (filtered_addrs.find(addresses[n], dummy_pos) == FALSE)
  409.       filtered_addrs += addresses[n];
  410.   // print out all addressess
  411.   text_edit_output->append(QString("Found %1  agents:n")
  412.    .arg(filtered_addrs.size()));
  413.   for (int m=0; m < filtered_addrs.size(); ++m)
  414.     text_edit_output->append(QString("Answer received from: %1n")
  415.      .arg(filtered_addrs[m].get_printable()));
  416. }
  417. // Handle start/stop of traps
  418. void MainWindow::push_button_traps_toggled(bool isOn)
  419. {
  420.   if (!snmp)
  421.     return;
  422.   // lock port input field while waiting for traps
  423.   line_edit_trap_port->setEnabled(!isOn);
  424.   if (isOn)
  425.   {
  426.     // Start receiving traps
  427.     // get the port
  428.     int port = line_edit_trap_port->text().toUInt();
  429.     // Set the trap listen port for this Snmp object
  430.     snmp->notify_set_listen_port(port);
  431.     OidCollection oidc;
  432.     TargetCollection targetc;
  433.     text_edit_output->append(
  434.       QString("Trying to register for traps on port %1.n").arg(port));
  435.     int status = snmp->notify_register(oidc, targetc, callback, this);
  436.     if (status != SNMP_CLASS_SUCCESS)
  437.     {
  438.       text_edit_output->append(
  439. QString("Error register for traps (%1): %2.n").arg(status)
  440.        .arg(snmp->error_msg(status)));
  441.       line_edit_trap_port->setEnabled(true);
  442.       push_button_traps->setOn(false);
  443.       return;
  444.     }
  445.     else
  446.       text_edit_output->append("Registered success.n");
  447.     // Start the timer
  448.     timer.start(100);
  449.   }
  450.   else
  451.   {
  452.     // stop receiving traps
  453.     snmp->notify_unregister();
  454.     text_edit_output->append("Stopped receiving traps.n");
  455.   }
  456. }