📄 subagent.c
字号:
/* * AgentX sub-agent */#include "config.h"#include <sys/types.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#include <sys/errno.h>#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#include "asn1.h"#include "snmp_api.h"#include "snmp_impl.h"#include "snmp_client.h"#include "snmp.h"#include "snmp_vars.h"#include "snmp_agent.h"#include "var_struct.h"#include "snmpd.h"#include "agentx/protocol.h"#include "agentx/client.h"#include "default_store.h"#include "ds_agent.h"#include "callback.h"#include "agent_registry.h"#include "agent_callbacks.h"#include "agent_trap.h"#include "snmp_debug.h"#include "mib_module_config.h"#ifdef USING_MIBII_SYSORTABLE_MODULE#include "mibII/sysORTable.h"#endif#include "system.h"struct agent_set_info { int transID; int mode; time_t uptime; struct snmp_session *sess; struct variable_list *var_list; struct agent_set_info *next;};static struct agent_set_info *Sets;voidsave_set_vars( struct snmp_session *ss, struct snmp_pdu *pdu ){ struct agent_set_info *ptr; struct timeval now; struct snmp_pdu *pdu2; extern struct timeval starttime; ptr = (struct agent_set_info *)malloc(sizeof(struct agent_set_info)); if (ptr == NULL ) return; /* * Save the important information */ ptr->transID = pdu->transid; ptr->sess = ss; ptr->mode = RESERVE1; gettimeofday(&now, NULL); ptr->uptime = calculate_time_diff(&now, &starttime); /* Lazy way to copy the variables! */ pdu2 = snmp_clone_pdu( pdu ); if ( pdu2 == NULL ) { free( ptr ); return; } ptr->var_list = pdu2->variables; pdu2->variables = NULL; snmp_free_pdu( pdu2 ); ptr->next = Sets; Sets = ptr;}voidrestore_set_vars( struct agent_snmp_session *asp ){ struct agent_set_info *ptr; for ( ptr=Sets ; ptr != NULL ; ptr=ptr->next ) if ( ptr->sess == asp->session && ptr->transID == asp->pdu->transid ) { if ( ptr->var_list == NULL ) return; asp->rw = WRITE; asp->pdu->variables = ptr->var_list; asp->start = ptr->var_list; asp->end = ptr->var_list; while ( asp->end->next_variable ) asp->end = asp->end->next_variable; ptr->mode = asp->mode; return; } return;}intset_mode( struct snmp_session *ss, struct snmp_pdu *pdu ){ struct agent_set_info *ptr; for ( ptr=Sets ; ptr != NULL ; ptr=ptr->next ) if ( ptr->sess == ss && ptr->transID == pdu->transid ) return ptr->mode; return -1;}voidfree_set_vars( struct snmp_session *ss, struct snmp_pdu *pdu ){ struct agent_set_info *ptr, *prev=NULL; for ( ptr=Sets ; ptr != NULL ; ptr=ptr->next ) if ( ptr->sess == ss && ptr->transID == pdu->transid ) { if ( prev ) prev->next = ptr->next; else Sets = ptr->next; snmp_free_varbind(ptr->var_list); free(ptr); return; }}inthandle_agentx_packet(int operation, struct snmp_session *session, int reqid, struct snmp_pdu *pdu, void *magic){ struct agent_snmp_session *asp; int status, allDone, i; struct variable_list *var_ptr, *var_ptr2; asp = init_agent_snmp_session( session, snmp_clone_pdu(pdu) ); DEBUGMSGTL(("agentx/subagent","handling agentx request....\n")); switch (pdu->command) { case AGENTX_MSG_GET: DEBUGMSGTL(("agentx/subagent"," -> get\n")); status = handle_next_pass( asp ); break; case AGENTX_MSG_GETBULK: DEBUGMSGTL(("agentx/subagent"," -> getbulk\n")); /* * GETBULKS require multiple passes. The first pass handles the * explicitly requested varbinds, and subsequent passes append * to the existing var_op_list. Each pass (after the first) * uses the results of the preceeding pass as the input list * (delimited by the start & end pointers. * Processing is terminated if all entries in a pass are * EndOfMib, or the maximum number of repetitions are made. */ asp->exact = FALSE; /* * Limit max repetitions to something reasonable * XXX: We should figure out what will fit somehow... */ if ( asp->pdu->errindex > 100 ) asp->pdu->errindex = 100; status = handle_next_pass( asp ); /* First pass */ if ( status != SNMP_ERR_NOERROR ) break; while ( asp->pdu->errstat-- > 0 ) /* Skip non-repeaters */ asp->start = asp->start->next_variable; asp->pdu->errindex--; /* First repetition was handled above */ while ( asp->pdu->errindex-- > 0 ) { /* Process repeaters */ /* * Add new variable structures for the * repeating elements, ready for the next pass. * Also check that these are not all EndOfMib */ allDone = TRUE; /* Check for some content */ for ( var_ptr = asp->start; var_ptr != asp->end->next_variable; var_ptr = var_ptr->next_variable ) { /* XXX: we don't know the size of the next OID, so assume the maximum length */ var_ptr2 = snmp_add_null_var(asp->pdu, var_ptr->name, MAX_OID_LEN); for ( i=var_ptr->name_length ; i<MAX_OID_LEN ; i++) var_ptr2->name[i] = '\0'; var_ptr2->name_length = var_ptr->name_length; if ( var_ptr->type != SNMP_ENDOFMIBVIEW ) allDone = FALSE; } if ( allDone ) break; asp->start = asp->end->next_variable; while ( asp->end->next_variable != NULL ) asp->end = asp->end->next_variable; status = handle_next_pass( asp ); if ( status != SNMP_ERR_NOERROR ) break; } break; case AGENTX_MSG_GETNEXT: DEBUGMSGTL(("agentx/subagent"," -> getnext\n")); asp->exact = FALSE; status = handle_next_pass( asp ); break; case AGENTX_MSG_TESTSET: DEBUGMSGTL(("agentx/subagent"," -> testset\n")); /* * In the UCD architecture the first two passes through var_op_list * verify that all types, lengths, and values are valid * and may reserve resources. * These correspond to the first AgentX pass - TESTSET */ asp->rw = WRITE; asp->mode = RESERVE1; save_set_vars( session, pdu ); status = handle_next_pass( asp ); if ( status != SNMP_ERR_NOERROR ) { asp->mode = FREE; (void) handle_next_pass( asp ); free_set_vars( session, pdu ); break; } asp->mode = RESERVE2; status = handle_next_pass( asp ); if ( status != SNMP_ERR_NOERROR ) { asp->mode = FREE; (void) handle_next_pass( asp ); free_set_vars( session, pdu ); } break; /* * The third and fourth passes in the UCD architecture * correspond to distinct AgentX passes, * as does the "undo" pass, in case of errors elsewhere */ case AGENTX_MSG_COMMITSET: DEBUGMSGTL(("agentx/subagent"," -> commitset\n")); asp->mode = ACTION; restore_set_vars( asp ); if ( asp->pdu->variables == NULL ) status = AGENTX_ERR_PROCESSING_ERROR; else status = handle_next_pass( asp ); if ( status != SNMP_ERR_NOERROR ) { asp->mode = UNDO; (void) handle_next_pass( asp ); free_set_vars( session, pdu ); } asp->pdu->variables = NULL; break; case AGENTX_MSG_CLEANUPSET: DEBUGMSGTL(("agentx/subagent"," -> cleanupset\n")); switch ( set_mode( session, pdu )) { case RESERVE1: case RESERVE2: case UNDO: asp->mode = FREE; break; case ACTION: asp->mode = COMMIT; break; } restore_set_vars( asp ); if ( asp->pdu->variables == NULL ) status = AGENTX_ERR_PROCESSING_ERROR; else status = handle_next_pass( asp ); free_set_vars( session, pdu ); asp->pdu->variables = NULL; break; case AGENTX_MSG_UNDOSET: DEBUGMSGTL(("agentx/subagent"," -> undoset\n")); asp->mode = UNDO; restore_set_vars( asp ); if ( asp->pdu->variables == NULL ) status = AGENTX_ERR_PROCESSING_ERROR; else status = handle_next_pass( asp ); free_set_vars( session, pdu ); asp->pdu->variables = NULL; break; case AGENTX_MSG_RESPONSE: DEBUGMSGTL(("agentx/subagent"," -> response\n")); free( asp ); return 0; default: DEBUGMSGTL(("agentx/subagent"," -> unknown (%d)\n", pdu->command )); free( asp ); return 0; } if ( asp->outstanding_requests == NULL ) { asp->pdu->command = AGENTX_MSG_RESPONSE; asp->pdu->errstat = status; snmp_send( asp->session, asp->pdu ); free( asp ); } DEBUGMSGTL(("agentx/subagent"," FINISHED\n\n")); return 1;}extern struct snmp_session *main_session; /* from snmp_agent.c */intagentx_registration_callback(int majorID, int minorID, void *serverarg, void *clientarg) { struct register_parameters *reg_parms = (struct register_parameters *) serverarg; struct snmp_session *agentx_ss = (struct snmp_session *) clientarg; if (minorID == SNMPD_CALLBACK_REGISTER_OID) return agentx_register(agentx_ss, reg_parms->name, reg_parms->namelen, reg_parms->priority, reg_parms->range_subid, reg_parms->range_ubound); else return agentx_unregister(agentx_ss, reg_parms->name, reg_parms->namelen, reg_parms->priority, reg_parms->range_subid, reg_parms->range_ubound);}#ifdef USING_MIBII_SYSORTABLE_MODULEintagentx_sysOR_callback(int majorID, int minorID, void *serverarg, void *clientarg) { struct register_sysOR_parameters *reg_parms = (struct register_sysOR_parameters *) serverarg; struct snmp_session *agentx_ss = (struct snmp_session *) clientarg; if (minorID == SNMPD_CALLBACK_REG_SYSOR) return agentx_add_agentcaps(agentx_ss, reg_parms->name, reg_parms->namelen, reg_parms->descr); else return agentx_remove_agentcaps(agentx_ss, reg_parms->name, reg_parms->namelen);}#endifstatic intsubagent_shutdown(int majorID, int minorID, void *serverarg, void *clientarg) { struct snmp_session *thesession = (struct snmp_session *) clientarg; DEBUGMSGTL(("agentx/subagent","shutting down session....\n")); if (thesession == NULL) { DEBUGMSGTL(("agentx/subagent","Empty session to shutdown\n")); return 0; } agentx_close_session(thesession, AGENTX_CLOSE_SHUTDOWN); snmp_close(thesession); free(thesession); DEBUGMSGTL(("agentx/subagent","shut down finished.\n")); return 1;}static intsubagent_register_for_traps(int majorID, int minorID, void *serverarg, void *clientarg) { struct snmp_session *thesession = (struct snmp_session *) clientarg; DEBUGMSGTL(("agentx/subagent","registering trap session....\n")); if (thesession == NULL) { DEBUGMSGTL(("agentx/subagent","No session to register\n")); return 0; } if (add_trap_session( thesession, AGENTX_MSG_NOTIFY, AGENTX_VERSION_1) == 0){ DEBUGMSGTL(("agentx/subagent","Trap session registration failed\n")); return 0; } DEBUGMSGTL(("agentx/subagent","Trap session registered OK\n")); return 1;}voidsubagent_pre_init( void ){ struct snmp_session sess; DEBUGMSGTL(("agentx/subagent","initializing....\n")); if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != SUB_AGENT ) return; snmp_sess_init( &sess ); sess.version = AGENTX_VERSION_1; sess.peername = strdup(AGENTX_SOCKET); sess.retries = SNMP_DEFAULT_RETRIES; sess.timeout = SNMP_DEFAULT_TIMEOUT; sess.flags |= SNMP_FLAGS_STREAM_SOCKET; sess.local_port = 0; /* client */ sess.callback = handle_agentx_packet; sess.authenticator = NULL; main_session = snmp_open_ex( &sess, 0, agentx_parse, 0, agentx_build, agentx_check_packet ); if ( main_session == NULL ) { /* diagnose snmp_open errors with the input struct snmp_session pointer */ snmp_sess_perror("subagent_pre_init", &sess); exit(1); } if ( agentx_open_session( main_session ) < 0 ) { snmp_close( main_session ); exit(1); } snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_PREMIB_READ_CONFIG, subagent_register_for_traps, main_session); snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN, subagent_shutdown, main_session); snmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_OID, agentx_registration_callback, main_session); snmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREGISTER_OID, agentx_registration_callback, main_session);#ifdef USING_MIBII_SYSORTABLE_MODULE snmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REG_SYSOR, agentx_sysOR_callback, main_session); snmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREG_SYSOR, agentx_sysOR_callback, main_session);#endif DEBUGMSGTL(("agentx/subagent","initializing.... DONE\n"));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -