Advertisement
rockdrilla

Boost::Asio and Net-SNMP

Jul 30th, 2014
708
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.05 KB | None | 0 0
  1. /*
  2. originally written by Moshe Levi
  3. http://blog-moshe.blogspot.com/2012/10/boost-asio-with-net-snmp.html
  4.  
  5. compile:
  6. $ g++ source.cpp -lboost_system -lsnmp
  7. */
  8.  
  9. #include <iostream>
  10. #include <string>
  11.  
  12. #include <boost/asio.hpp>
  13. #include <boost/bind.hpp>
  14. #include <boost/function.hpp>
  15.  
  16. #include <net-snmp/net-snmp-config.h>
  17. #include <net-snmp/net-snmp-includes.h>
  18.  
  19. typedef boost::function<void(std::string)> SnmpHandler;
  20.  
  21. class SnmpConnection {
  22. private:
  23.     boost::asio::ip::udp::socket m_boost_sock;
  24.     void* m_netsnmp_handle;
  25.  
  26.     void handle_snmp_req(
  27.         const boost::system::error_code& ec
  28.     ,   size_t bytes_transferred
  29.     ,   struct snmp_pdu* pdu
  30.     ,   SnmpHandler handler
  31.     );
  32.     void handle_snmp_res(
  33.         const boost::system::error_code& ec
  34.     ,   size_t bytes_transferred
  35.     ,   SnmpHandler handler
  36.     );
  37.  
  38.     static int async_response(
  39.         int operation
  40.     ,   struct snmp_session* sp
  41.     ,   int reqid
  42.     ,   struct snmp_pdu* pdu
  43.     ,   void* magic
  44.     );
  45.  
  46. public:
  47.     SnmpConnection(boost::asio::io_service& io_service)
  48.     : m_boost_sock(io_service)
  49.     , m_netsnmp_handle(NULL)
  50.     {};
  51.  
  52.     ~SnmpConnection() {
  53.         snmp_sess_close(m_netsnmp_handle);
  54.     }
  55.  
  56.     void connect(
  57.         long version
  58.     ,   const std::string& peername
  59.     ,   const std::string& community
  60.     );
  61.     void async_snmp_get(
  62.         const std::string& snmp_oid
  63.     ,   SnmpHandler handler
  64.     );
  65.     void async_snmp_set(
  66.         const std::string& snmp_oid
  67.     ,   const int type
  68.     ,   const std::string& value
  69.     ,   SnmpHandler handler
  70.     );
  71. };
  72.  
  73.  
  74. void SnmpConnection::connect(
  75.     long version
  76. ,   const std::string& peername
  77. ,   const std::string& community
  78. ){
  79.     struct snmp_session sess;
  80.  
  81.     //initialize session
  82.     snmp_sess_init(&sess);
  83.     sess.version = version;
  84.     sess.peername = strdup(peername.c_str());
  85.     sess.community = reinterpret_cast<u_char*>(strdup(community.c_str()));
  86.     sess.community_len = community.size();
  87.     sess.callback = async_response;
  88.     m_netsnmp_handle = snmp_sess_open(&sess);
  89.     free(sess.peername);
  90.     free(sess.community);
  91.     netsnmp_transport* transport = snmp_sess_transport(m_netsnmp_handle);
  92.     m_boost_sock.assign(boost::asio::ip::udp::v4(), transport->sock);
  93.     //put the socket into non-blocking mode
  94.     boost::asio::ip::udp::socket::non_blocking_io non_blocking_io(true);
  95.     m_boost_sock.io_control(non_blocking_io);
  96. }
  97.  
  98. void SnmpConnection::async_snmp_get(
  99.     const std::string& snmp_oid
  100. ,   SnmpHandler handler
  101. ) {
  102.     struct snmp_pdu* pdu = NULL;
  103.     oid anOID[MAX_OID_LEN];
  104.     size_t anOID_len = MAX_OID_LEN;
  105.  
  106.     pdu = snmp_pdu_create(SNMP_MSG_GET);
  107.     if (!snmp_parse_oid(snmp_oid.c_str(), anOID, &anOID_len)) {
  108.         snmp_perror(snmp_oid.c_str());
  109.         std::cout << "error snmp_parse_oid" << std::endl;
  110.     }
  111.  
  112.     snmp_add_null_var(pdu, anOID, anOID_len);
  113.     m_boost_sock.async_send(
  114.         boost::asio::null_buffers(),
  115.         boost::bind(
  116.             &SnmpConnection::handle_snmp_req
  117.         ,   this
  118.         ,   boost::asio::placeholders::error
  119.         ,   boost::asio::placeholders::bytes_transferred
  120.         ,   pdu
  121.         ,   handler
  122.         )
  123.     );
  124. }
  125.  
  126. void SnmpConnection::handle_snmp_req(
  127.     const boost::system::error_code& ec
  128. ,   size_t bytes_transferred
  129. ,   struct snmp_pdu* pdu
  130. ,   SnmpHandler handler
  131. ) {
  132.     if (!m_boost_sock.is_open()) {
  133.         return;
  134.     }
  135.  
  136.     if (ec) {
  137.         std::cout << "error SnmpConnection::handle_snmp_req" << std::endl;
  138.     } else {
  139.         //notify net-snmp library that it can perform a write
  140.         snmp_sess_send(m_netsnmp_handle, pdu);
  141.         m_boost_sock.async_receive(
  142.             boost::asio::null_buffers(),
  143.             boost::bind(
  144.                 &SnmpConnection::handle_snmp_res
  145.             ,   this
  146.             ,   boost::asio::placeholders::error
  147.             ,   boost::asio::placeholders::bytes_transferred
  148.             ,   handler
  149.             )
  150.         );
  151.     }
  152. }
  153.  
  154. void SnmpConnection::handle_snmp_res(
  155.     const boost::system::error_code& ec
  156. ,   size_t bytes_transferred
  157. ,   SnmpHandler handler
  158. ) {
  159.     if (!m_boost_sock.is_open()) {
  160.         return;
  161.     }
  162.  
  163.     if (ec) {
  164.         std::cout << "error SnmpConnection::handle_snmp_res" << std::endl;
  165.     } else {
  166.         fd_set snmp_fds;
  167.         FD_ZERO(&snmp_fds);
  168.         FD_SET(m_boost_sock.native(), &snmp_fds);
  169.         snmp_sess_read(m_netsnmp_handle, &snmp_fds);
  170. //      handler(snmp_response);//wtf?!
  171.     }
  172. }
  173.  
  174. //--------------------
  175.  
  176. int SnmpConnection::async_response(
  177.     int operation
  178. ,   struct snmp_session* sp
  179. ,   int reqid
  180. ,   struct snmp_pdu* pdu
  181. ,   void* magic
  182. ) {
  183.     if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
  184.         char buf[1024];
  185.  
  186.         if (pdu->errstat == SNMP_ERR_NOERROR) {
  187.             if (pdu->variables) {
  188.                 print_variable(pdu->variables->name, pdu->variables->name_length, pdu->variables);
  189. /*
  190.                 snprint_variable(
  191.                     buf
  192.                 ,   sizeof(buf)
  193.                 ,   pdu->variables->name
  194.                 ,   pdu->variables->name_length
  195.                 ,   pdu->variables
  196.                 );
  197.                 SnmpConnection::response_ = buf;
  198. // */
  199.             }
  200.         }
  201.     }
  202.  
  203.     return 1;
  204. }
  205.  
  206. //--------------------
  207.  
  208. void snmp_print(
  209.     std::string result
  210. ,   int num
  211. ) {
  212.     std::cout << "result " << result << std::endl;
  213.     std::cout << "num " << num << std::endl;
  214. }
  215.  
  216. int main() {
  217.     boost::asio::io_service snmp_service;
  218.     SnmpConnection snmp_conn(snmp_service);
  219.     snmp_conn.connect(SNMP_VERSION_2c, std::string("192.168.1.1"), std::string("public"));
  220.     snmp_conn.async_snmp_get(std::string(".1.3.6.1.2.1.1.4.0"), boost::bind(snmp_print, _1, 3));
  221.     snmp_service.run();
  222.     return 0;
  223. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement