📄 subagent.c
字号:
/* * AgentX sub-agent */#include <net-snmp/net-snmp-config.h>#include <sys/types.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#if TIME_WITH_SYS_TIME# ifdef WIN32# include <sys/timeb.h># else# include <sys/time.h># endif# include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#if HAVE_WINSOCK_H#include <winsock.h>#endif#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-agent-includes.h>#include <net-snmp/library/snmp_assert.h>#include "snmpd.h"#include "agentx/protocol.h"#include "agentx/client.h"#include "agentx/agentx_config.h"#include <net-snmp/agent/agent_callbacks.h>#include <net-snmp/agent/agent_trap.h>#ifdef USING_MIBII_SYSORTABLE_MODULE#include "mibII/sysORTable.h"#endif#include "subagent.h"#ifdef USING_AGENTX_SUBAGENT_MODULEstatic SNMPCallback subagent_register_ping_alarm;static SNMPAlarmCallback agentx_reopen_session;void agentx_register_callbacks(netsnmp_session * s);void agentx_unregister_callbacks(netsnmp_session * ss);int handle_subagent_response(int op, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic);int handle_subagent_set_response(int op, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic);void subagent_startup_callback(unsigned int clientreg, void *clientarg);int subagent_open_master_session(void);typedef struct _net_snmpsubagent_magic_s { int original_command; netsnmp_session *session; netsnmp_variable_list *ovars;} ns_subagent_magic;struct agent_netsnmp_set_info { int transID; int mode; int errstat; time_t uptime; netsnmp_session *sess; netsnmp_variable_list *var_list; struct agent_netsnmp_set_info *next;};static struct agent_netsnmp_set_info *Sets = NULL;netsnmp_session *agentx_callback_sess = NULL;extern int callback_master_num;extern netsnmp_session *main_session; /* from snmp_agent.c */intsubagent_startup(int majorID, int minorID, void *serverarg, void *clientarg){ DEBUGMSGTL(("agentx/subagent", "connecting to master...\n")); /* * if a valid ping interval has been defined, call agentx_reopen_session * to try to connect to master or setup a ping alarm if it couldn't * succeed. if no ping interval was set up, just try to connect once. */ if (netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL) > 0) agentx_reopen_session(0, NULL); else { subagent_open_master_session(); } return 0;}/** * init subagent callback (local) session and connect to master agent * * @returns 0 for success, !0 otherwise */intsubagent_init(void){ static int init = 0; int rc = 0; DEBUGMSGTL(("agentx/subagent", "initializing....\n")); if (++init != 1) return 0; netsnmp_assert(netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT);#ifndef NETSNMP_TRANSPORT_CALLBACK_DOMAIN snmp_log(LOG_WARNING,"AgentX subagent has been disabled because " "the callback transport is not available.\n"); return -1;#endif /* NETSNMP_TRANSPORT_CALLBACK_DOMAIN */ /* * open (local) callback session */ if (agentx_callback_sess == NULL) { agentx_callback_sess = netsnmp_callback_open(callback_master_num, handle_subagent_response, NULL, NULL); DEBUGMSGTL(("agentx/subagent", "subagent_init sess %08x\n", agentx_callback_sess)); } if (NULL == agentx_callback_sess) return -1; snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, subagent_startup, NULL); DEBUGMSGTL(("agentx/subagent", "initializing.... DONE\n")); return rc;}voidnetsnmp_enable_subagent(void) { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, SUB_AGENT);}struct agent_netsnmp_set_info *save_set_vars(netsnmp_session * ss, netsnmp_pdu *pdu){ struct agent_netsnmp_set_info *ptr; struct timeval now; extern struct timeval starttime; ptr = (struct agent_netsnmp_set_info *) malloc(sizeof(struct agent_netsnmp_set_info)); if (ptr == NULL) return NULL; /* * Save the important information */ ptr->transID = pdu->transid; ptr->sess = ss; ptr->mode = SNMP_MSG_INTERNAL_SET_RESERVE1; gettimeofday(&now, NULL); ptr->uptime = calculate_time_diff(&now, &starttime); ptr->var_list = snmp_clone_varbind(pdu->variables); if (ptr->var_list == NULL) { free(ptr); return NULL; } ptr->next = Sets; Sets = ptr; return ptr;}struct agent_netsnmp_set_info *restore_set_vars(netsnmp_session * sess, netsnmp_pdu *pdu){ struct agent_netsnmp_set_info *ptr; for (ptr = Sets; ptr != NULL; ptr = ptr->next) if (ptr->sess == sess && ptr->transID == pdu->transid) break; if (ptr == NULL || ptr->var_list == NULL) return NULL; pdu->variables = snmp_clone_varbind(ptr->var_list); if (pdu->variables == NULL) return NULL; return ptr;}voidfree_set_vars(netsnmp_session * ss, netsnmp_pdu *pdu){ struct agent_netsnmp_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; } prev = ptr; }}inthandle_agentx_packet(int operation, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic){ struct agent_netsnmp_set_info *asi = NULL; snmp_callback mycallback; netsnmp_pdu *internal_pdu = NULL; void *retmagic = NULL; ns_subagent_magic *smagic = NULL; if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) { struct synch_state *state = (struct synch_state *) magic; int period = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL); DEBUGMSGTL(("agentx/subagent", "transport disconnect indication\n")); /* * deal with existing session. This happend if agentx sends * a message to the master, but the master goes away before * a response is sent. agentx will spin in snmp_synch_response_cb, * waiting for a response. At the very least, the waiting * flag must be set to break that loop. The rest is copied * from disconnect handling in snmp_sync_input. */ if(state) { state->waiting = 0; state->pdu = NULL; state->status = STAT_ERROR; session->s_snmp_errno = SNMPERR_ABORT; SET_SNMP_ERROR(SNMPERR_ABORT); } /* * Deregister the ping alarm, if any, and invalidate all other * references to this session. */ if (session->securityModel != SNMP_DEFAULT_SECMODEL) { snmp_alarm_unregister(session->securityModel); } snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_STOP, (void *) session); agentx_unregister_callbacks(session); remove_trap_session(session); register_mib_detach(); main_session = NULL; if (period != 0) { /* * Pings are enabled, so periodically attempt to re-establish contact * with the master agent. Don't worry about the handle, * agentx_reopen_session unregisters itself if it succeeds in talking * to the master agent. */ snmp_alarm_register(period, SA_REPEAT, agentx_reopen_session, NULL); } return 0; } else if (operation != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { DEBUGMSGTL(("agentx/subagent", "unexpected callback op %d\n", operation)); return 1; } /* * ok, we have a pdu from the net. Modify as needed */ DEBUGMSGTL(("agentx/subagent", "handling agentx request (req=0x%x,trans=" "0x%x,sess=0x%x)\n", pdu->reqid,pdu->transid, pdu->sessid)); pdu->version = AGENTX_VERSION_1; pdu->flags |= UCD_MSG_FLAG_ALWAYS_IN_VIEW; if (pdu->command == AGENTX_MSG_GET || pdu->command == AGENTX_MSG_GETNEXT || pdu->command == AGENTX_MSG_GETBULK) { smagic = (ns_subagent_magic *) calloc(1, sizeof(ns_subagent_magic)); if (smagic == NULL) { DEBUGMSGTL(("agentx/subagent", "couldn't malloc() smagic\n")); return 1; } smagic->original_command = pdu->command; smagic->session = session; smagic->ovars = NULL; retmagic = (void *) smagic; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -