📄 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#if HAVE_DMALLOC_H#include <dmalloc.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 <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"static 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);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;voidinit_subagent(void){#ifndef SNMP_TRANSPORT_CALLBACK_DOMAIN snmp_log(LOG_WARNING,"AgentX subagent has been disabled because " "the callback transport is not available.\n"); return;#else if (agentx_callback_sess == NULL) { agentx_callback_sess = netsnmp_callback_open(callback_master_num, handle_subagent_response, NULL, NULL); DEBUGMSGTL(("agentx/subagent", "init_subagent sess %08x\n", agentx_callback_sess)); }#endif /* SNMP_TRANSPORT_CALLBACK_DOMAIN */}#ifdef USING_AGENTX_SUBAGENT_MODULEvoidnetsnmp_enable_subagent(void) { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, SUB_AGENT);}#endif /* USING_AGENTX_SUBAGENT_MODULE */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; }}extern netsnmp_session *main_session; /* from snmp_agent.c */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; } switch (pdu->command) { case AGENTX_MSG_GET: DEBUGMSGTL(("agentx/subagent", " -> get\n")); pdu->command = SNMP_MSG_GET; mycallback = handle_subagent_response; break; case AGENTX_MSG_GETNEXT: DEBUGMSGTL(("agentx/subagent", " -> getnext\n")); pdu->command = SNMP_MSG_GETNEXT; /* * We have to save a copy of the original variable list here because * if the master agent has requested scoping for some of the varbinds * that information is stored there. */ smagic->ovars = snmp_clone_varbind(pdu->variables); DEBUGMSGTL(("agentx/subagent", "saved variables\n")); mycallback = handle_subagent_response; break; case AGENTX_MSG_GETBULK: /* * WWWXXX */ DEBUGMSGTL(("agentx/subagent", " -> getbulk\n")); pdu->command = SNMP_MSG_GETBULK; /* * We have to save a copy of the original variable list here because * if the master agent has requested scoping for some of the varbinds * that information is stored there. */ smagic->ovars = snmp_clone_varbind(pdu->variables); DEBUGMSGTL(("agentx/subagent", "saved variables at %p\n", smagic->ovars)); mycallback = handle_subagent_response;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -