📄 uxsnmp.cpp
字号:
/*=================================================================== U X S N M P . C P P UXSNMP CLASS DECLARATION Description: HPUX version of Snmp class Language: ANSI C++ Operating System: HP-UX 9.0 Author: Peter E Mellquist HP RND R & D Date: July 27, 1999 Changes:=====================================================================*/char snmp_cpp_version[]="#(@)SNMP++ 2.8 $Header: uxsnmp.cpp,v 1.48 97/03/26 09:22:51 hmgr Exp $";// For debuggin cout's#include <iostream.h>#ifdef sun#include <collect.h>#endif//-----[ includes ]----------------------------------------------------extern "C"{#include <stdio.h> // standard io#include <stdlib.h> // need for malloc#include <unistd.h> // unix#include <sys/socket.h> // bsd socket stuff#include <netinet/in.h> // network types#include <arpa/inet.h> // arpa types#include <sys/types.h> // system types#include <sys/time.h> // time stuff#include <errno.h> // ux errs}#define _INCLUDE_SNMP_ERR_STRINGS//----[ snmp++ includes ]----------------------------------------------#include "oid.h" // class def for oids#include "oid_def.h" // class def for well known trap oids#include "vb.h" // class def for vbs#include "address.h" // class def for addresses#include "snmp_pp.h" // class def for this module#include "msgqueue.h" // message queue#include "notifyqueue.h" // notification queue#include "eventlist.h" // queue for holding outstanding messages#include "snmpmsg.h" // asn serialization class//-----[ special includes ]-------------------------------------------extern "C"{//------------[ if using Wind-U, then bring in the ms-windows header ]#ifdef WU_APPWORD app_hinst;#elsetypedef short WORD;typedef long DWORD;#endif}#ifdef _DEBUG#define SNMPDEBUG(s) printf(s)#else#define SNMPDEBUG(s)#endif//-----[ macros ]------------------------------------------------------#define DEFAULT_TIMEOUT 1000 // one second defualt timeout#define DEFAULT_RETRIES 1 // no retry default#define SNMP_PORT 161 // port # for SNMP#define SNMP_TRAP_PORT 162 // port # for SNMP traps#define MAX_SNMP_PACKET 2048 // maximum snmp packet len#define MANY_AT_A_TIME 20 // many at a time size#define MAX_GET_MANY 51 // maximum get many size#define MAX_RID 32767 // max rid to use#define MIN_RID 1000 // min rid to use//--------[ globals ]---------------------------------------------------int ref_count = 0; // reference count of snmp objectslong int current_rid = MAX_RID; // current rid to use//--------------[ well known trap ids ]-----------------------------------const coldStartOid coldStart;const warmStartOid warmStart;const linkDownOid linkDown;const linkUpOid linkUp;const authenticationFailureOid authenticationFailure;const egpNeighborLossOid egpNeighborLoss;const snmpTrapEnterpriseOid snmpTrapEnterprise;//--------[ make the pdu request id ]-----------------------------------// return a unique rid, clock can be too slow , so use current_ridlong MyMakeReqId(){ do { current_rid++; if ( current_rid > MAX_RID) current_rid = MIN_RID; } while (snmpEventList->GetEntry(current_rid)); return (long) current_rid;}//---------[ Send SNMP Request ]---------------------------------------// Send out a snmp requestint send_snmp_request( int sock, unsigned char *send_buf, size_t send_len, Address & address){ struct sockaddr_in agent_addr; // send socket struct // UX only supports UDP type addresses (addr and port) right now if (address.get_type() != type_udp) { return -1;// unsupported address type } // prepare the destination address memset(&agent_addr, 0, sizeof(agent_addr)); agent_addr.sin_family = AF_INET; agent_addr.sin_addr.s_addr = inet_addr(((IpAddress &)address).IpAddress::get_printable()); agent_addr.sin_port = htons(((UdpAddress &)address).get_port()); // cout << "Port # " << ((UdpAddress &) address.get_port() << "\n"; // send the packet // pdu_container->pdu_sent(); if ( sendto( sock, (char*) send_buf, send_len, 0, (struct sockaddr*) &agent_addr, sizeof(agent_addr)) < 0) { SNMPDEBUG(strerror(errno)); return -1; // send error! } return 0;}//---------[ receive a snmp response ]---------------------------------// Receive a response from the specified socket.// This function does not set the request id in the pdu if// any error occur in receiving or parsing. This is important // because the caller initializes this to zero and checks it to // see whether it has been changed to a valid value. The // return value is the normal PDU status or SNMP_CLASS_SUCCESS.// when we are successful in receiving a pdu. Otherwise it// is an error status.int receive_snmp_response( int sock, Pdu &pdu){ unsigned char receive_buffer[MAX_SNMP_PACKET]; long receive_buffer_len; // len of received data struct sockaddr_in from_addr;#ifdef LINUX socklen_t fromlen;#else int fromlen;#endif fromlen = sizeof(from_addr); // do the read do { receive_buffer_len = (long) recvfrom(sock, (char *) receive_buffer, MAX_SNMP_PACKET, 0, (struct sockaddr*) &from_addr, &fromlen); } while (receive_buffer_len < 0 && EINTR == errno); if (receive_buffer_len <= 0 ) // error or no data pending return SNMP_CLASS_TL_FAILED; SnmpMessage snmpmsg; if ( snmpmsg.load( receive_buffer, receive_buffer_len) != SNMP_CLASS_SUCCESS) return SNMP_CLASS_ERROR; OctetStr community_name; snmp_version version; if ( snmpmsg.unload( pdu, community_name, version) != SNMP_CLASS_SUCCESS) return SNMP_CLASS_ERROR; //-----[ check for error status stuff..] // an error status is a valid pdu, // the caller needs to know about it if ( pdu.get_error_status() != 0) return pdu.get_error_status(); return SNMP_CLASS_SUCCESS; // Success! return}//---------[ receive a snmp trap ]---------------------------------// Receive a trap from the specified socketint receive_snmp_notification( int sock, Pdu &pdu, CTarget &target){ unsigned char receive_buffer[MAX_SNMP_PACKET]; long receive_buffer_len; // len of received data struct sockaddr_in from_addr;#ifdef LINUX socklen_t fromlen;#else int fromlen;#endif fromlen = sizeof(from_addr); // do the read do { receive_buffer_len = (long) recvfrom(sock, (char *) receive_buffer, MAX_SNMP_PACKET, 0, (struct sockaddr*)&from_addr, &fromlen); } while (receive_buffer_len < 0 && EINTR == errno); if (receive_buffer_len <= 0 ) // error or no data pending return SNMP_CLASS_TL_FAILED; if (from_addr.sin_family != AF_INET) // sanity check return SNMP_CLASS_TL_FAILED; SnmpMessage snmpmsg; if ( snmpmsg.load( receive_buffer, receive_buffer_len) != SNMP_CLASS_SUCCESS) return SNMP_CLASS_ERROR; OctetStr community_name; snmp_version version; if ( snmpmsg.unload( pdu, community_name, version) != SNMP_CLASS_SUCCESS) return SNMP_CLASS_ERROR; IpAddress ipa( (char*) inet_ntoa( from_addr.sin_addr)); target.set_address( ipa); target.set_readcommunity( community_name); target.set_writecommunity( community_name); return SNMP_CLASS_SUCCESS; // Success! return}//--------[ map action ]------------------------------------------------// map the snmp++ action to a SMI pdu typevoid map_action( unsigned short action, unsigned short & pdu_action){ switch( action) { case sNMP_PDU_GET: case sNMP_PDU_GET_ASYNC: pdu_action = sNMP_PDU_GET; break; case sNMP_PDU_SET: case sNMP_PDU_SET_ASYNC: pdu_action = sNMP_PDU_SET; break; case sNMP_PDU_GETNEXT: case sNMP_PDU_GETNEXT_ASYNC: pdu_action = sNMP_PDU_GETNEXT; break; case sNMP_PDU_GETBULK: case sNMP_PDU_GETBULK_ASYNC: pdu_action = sNMP_PDU_GETBULK; break; default: pdu_action = sNMP_PDU_GET; // TM ?? error ?? break; }; // end switch}//------[ Snmp Class Constructor ]--------------------------------------Snmp::Snmp( int &status, unsigned short agent_port) // status of construction{ struct sockaddr_in mgr_addr; // intialize all the trap receiving member variables notify_targets = 0; notify_ids = 0; listen_addresses = 0; notifycallback = 0; notifycallback_data = 0; //int errno = 0; // open a socket to be used for the session if (( iv_snmp_session = (int) socket( AF_INET, SOCK_DGRAM,0)) < 0) { if (EMFILE == errno || ENOBUFS == errno || ENFILE == errno) { status = SNMP_CLASS_RESOURCE_UNAVAIL; } else if (EHOSTDOWN == errno) { status = SNMP_CLASS_TL_FAILED; } else { status = SNMP_CLASS_TL_UNSUPPORTED; } } else { // set up the manager socket attributes memset(&mgr_addr, 0, sizeof(mgr_addr)); mgr_addr.sin_family = AF_INET; mgr_addr.sin_addr.s_addr = htonl( INADDR_ANY); mgr_addr.sin_port = htons( agent_port); // bind the socket if ( bind( (int) iv_snmp_session, (struct sockaddr*) &mgr_addr, sizeof(mgr_addr)) < 0) { if (EADDRINUSE == errno) { status = SNMP_CLASS_TL_IN_USE; } else if (ENOBUFS == errno) { status = SNMP_CLASS_RESOURCE_UNAVAIL; } else if (errno == EAFNOSUPPORT){ status = SNMP_CLASS_TL_UNSUPPORTED; } else if (errno == ENETUNREACH || errno == EACCES){ status = SNMP_CLASS_TL_FAILED; } else { status = SNMP_CLASS_INTERNAL_ERROR; } } else { ref_count++; status = SNMP_CLASS_SUCCESS; if ( ref_count == 1) { // pdu_container = new Pdu_Container();#ifdef PDU_CONTAINER if ( pdu_container == NULL) { status = SNMP_CLASS_RESOURCE_UNAVAIL; close( (int) iv_snmp_session); }#endif // PDU_CONTAINER } } }#ifdef SNMPX11 // Tell X11 to watch our file descriptor status = SnmpX11AddInput( (int)iv_snmp_session, pdu_handler);#endif // SNMPX11 construct_status = status; return;};//---------[ Snmp Class Destructor ]----------------------------------Snmp::~Snmp(){ // if we failed during construction then don't try // to free stuff up that was not allocated if ( construct_status != SNMP_CLASS_SUCCESS) return; close( (int) iv_snmp_session); // close the dynamic socket ref_count--; // extra check for protection if ( ref_count < 0) ref_count = 0; if ( ref_count == 0) ; // delete pdu_container; // go through the snmpEventList and delete any outstanding // events on this socket snmpEventList->DeleteSocketEntry((int)iv_snmp_session); // shut down trap reception if used notify_unregister();#ifdef SNMPX11 // Tell X11 to stop watching our file descriptor SnmpX11RemoveInput(pdu_handler);#endif // SNMPX11};//-------------------[ returns error string ]--------------------------char * Snmp::error_msg( const int c){ return ((c<0)? ((c<MAX_NEG_ERROR)?nErrs[-(MAX_NEG_ERROR)+1]:nErrs[-c]): ((c>MAX_POS_ERROR)?pErrs[MAX_POS_ERROR+1]:pErrs[c]));}//------------------------[ get ]---------------------------------------int Snmp::get( Pdu &pdu, // pdu to use SnmpTarget &target) // get target{ pdu.set_type( sNMP_PDU_GET); return snmp_engine( pdu, // get pdu 0, // max repeaters 0, // non repeaters target, // target NULL, // callback for async only 0); // callback data};//------------------------[ get async ]----------------------------------int Snmp::get( Pdu &pdu, // pdu to use SnmpTarget &target, // destination target const snmp_callback callback, // async callback const void * callback_data) // callback data{ pdu.set_type( sNMP_PDU_GET_ASYNC); return snmp_engine( pdu, // get async pdu 0, // max repeaters 0, // non repeaters target, // target callback, // callback to use callback_data); // callback data};//------------------------[ get next ]-----------------------------------int Snmp::get_next( Pdu &pdu, // pdu to use SnmpTarget &target) // get target{ pdu.set_type( sNMP_PDU_GETNEXT); return snmp_engine( pdu, // pdu to get next 0, // max repeaters 0, // non repeaters target, // target NULL, // callback for async only 0); // callback data for async only};//------------------------[ get next async ]-----------------------------int Snmp::get_next( Pdu &pdu, // pdu to use SnmpTarget &target, // destination target const snmp_callback callback, // callback to use const void * callback_data) // callback data{ pdu.set_type( sNMP_PDU_GETNEXT_ASYNC); return snmp_engine( pdu, // pdu to get next 0, // max repeaters 0, // non repeaters target, // target callback, // callback callback_data); // callback data};//-------------------------[ set ]---------------------------------------int Snmp::set( Pdu &pdu, // pdu to use SnmpTarget &target) // target address{ pdu.set_type( sNMP_PDU_SET); return snmp_engine( pdu, // pdu to set 0, // max repeaters 0, // non repeaters target, // target NULL, // callback for async only 0); // callback data};//------------------------[ set async ]----------------------------------int Snmp::set( Pdu &pdu, // pdu to use
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -