snmpd.c
资源名称:snmp.src.rar [点击查看]
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:15k
源码类别:
SNMP编程
开发平台:
C/C++
- /*
- * snmpd.c - rrespond to SNMP queries from management stations
- *
- */
- /***********************************************************
- Copyright 1988, 1989 by Carnegie Mellon University
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of CMU not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ******************************************************************/
- #ifdef OS_VXWORKS
- #include <libsys/vos/vos_rtos.h>
- #include <global.h>
- #endif
- #include <ip/socket.h>
- #include <config.h>
- #include <stdio.h>
- #include <errno.h>
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #if HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <sys/types.h>
- #if HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #if HAVE_ARPA_INET_H
- #include <arpa/inet.h>
- #endif
- #if TIME_WITH_SYS_TIME
- # ifdef WIN32
- # include <sys/timeb.h>
- # else
- # include <time.h>
- # endif
- # include <time.h>
- #else
- # if HAVE_SYS_TIME_H
- # include <sys/time.h>
- # else
- # include <time.h>
- # endif
- #endif
- #if HAVE_SYS_SELECT_H
- #include <sys/select.h>
- #endif
- #if HAVE_SYS_SOCKET_H
- #include <sys/socket.h>
- #elif HAVE_WINSOCK_H
- #endif
- #if HAVE_NET_IF_H
- #include <net/if.h>
- #endif
- #if HAVE_INET_MIB2_H
- #include <inet/mib2.h>
- #endif
- #if HAVE_SYS_IOCTL_H
- #include <sys/ioctl.h>
- #endif
- #if HAVE_SYS_FILE_H
- #include <sys/file.h>
- #endif
- #ifdef HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #if HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #endif
- #include <signal.h>
- #ifdef HAVE_SYS_PARAM_H
- #include <sys/param.h>
- #endif
- #include <ip/inet.h>
- #ifndef FD_SET
- typedef long fd_mask;
- #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
- #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
- #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
- #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
- #define FD_ZERO(p) memset((p), 0, sizeof(*(p)))
- #endif
- #if HAVE_DMALLOC_H
- #include <dmalloc.h>
- #endif
- #include "asn1.h"
- #include "snmp_api.h"
- #include "snmp_impl.h"
- #include "read_config.h"
- #include "snmp.h"
- #include "mib.h"
- #include "m2m.h"
- #include "snmp_vars.h"
- #include "agent_read_config.h"
- #include "snmpv3.h"
- #include "callback.h"
- #include "snmp_alarm.h"
- #include "default_store.h"
- #include "mib_module_config.h"
- #include "snmp_client.h"
- #include "snmpd.h"
- #include "var_struct.h"
- #include "mibgroup/struct.h"
- #include "mibgroup/util_funcs.h"
- #include "snmp_debug.h"
- #include "mib_modules.h"
- #include "snmpusm.h"
- #include "tools.h"
- #include "lcd_time.h"
- #include "snmp_agent.h"
- #include "agent_trap.h"
- #include "ds_agent.h"
- #include "agent_read_config.h"
- #include "snmp_logging.h"
- #include "version.h"
- #include "mib_module_includes.h"
- #include "system.h"
- /*
- * Globals.
- */
- #ifdef USE_LIBWRAP
- #include <tcpd.h>
- int allow_severity = LOG_INFO;
- int deny_severity = LOG_WARNING;
- #endif /* USE_LIBWRAP */
- #define TIMETICK 500000L
- #define ONE_SEC 1000000L
- int log_addresses = 0;
- int snmp_dump_packet;
- int running = 1;
- int reconfig = 0;
- struct addrCache {
- in_addr_t addr;
- int status;
- #define UNUSED 0
- #define USED 1
- #define OLD 2
- };
- #define ADDRCACHE 10
- static struct addrCache addrCache[ADDRCACHE];
- static int lastAddrAge = 0;
- #define NUM_SOCKETS 32
- #ifdef USING_SMUX_MODULE
- static int sdlist[NUM_SOCKETS], sdlen = 0;
- int smux_listen_sd;
- #endif /* USING_SMUX_MODULE */
- /*
- * Prototypes.
- */
- int snmp_read_packet (int);
- int snmp_input (int, struct snmp_session *, int, struct snmp_pdu *, void *);
- int main (int, char **);
- static void SnmpTrapNodeDown (void);
- int receive(void);
- int snmp_check_packet(struct snmp_session*, struct soaddr);
- int snmp_check_parse(struct snmp_session*, struct snmp_pdu*, int);
- extern int gettimeofday(struct timeval *tp,struct timezone *tzp);
- extern void set_trapd_session_ptr (void);
- extern void init_trap_retry_timer(void);
- #ifdef SIGHUP
- RETSIGTYPE
- SnmpdReconfig(int a)
- {
- reconfig = 1;
- signal(SIGHUP, SnmpdReconfig);
- }
- #endif
- #ifdef SIGUSR1
- extern void dump_registry( void );
- RETSIGTYPE
- SnmpdDump(int a)
- {
- dump_registry();
- signal(SIGUSR1, SnmpdDump);
- }
- #endif
- static void
- SnmpTrapNodeDown(void)
- {
- send_easy_trap (SNMP_TRAP_ENTERPRISESPECIFIC, 2);
- /* XXX 2 - Node Down #define it as NODE_DOWN_TRAP */
- }
- void snmp_set_dump_verbose (int value)
- {
- ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, value);
- }
- /*******************************************************************-o-******
- * main
- *
- * Parameters:
- * argc
- * *argv[]
- *
- * Returns:
- * 0 Always succeeds. (?)
- *
- *
- * Setup and start the agent daemon.
- *
- * Also successfully EXITs with zero for some options.
- */
- extern ULONG snmp_source_ip;
- extern int output_error;
- int
- snmpd_init(void)
- {
- int ret;
- u_short dest_port = SNMP_PORT;
- #if HAVE_GETPID
- FILE *PID;
- #endif
- init_agent("snmpd"); /* do what we need to do first. */
- init_mib_modules();
- init_start_time();
- /* start library */
- init_snmp("snmpd");
- snmp_source_ip= INADDR_ANY;
- ret = init_master_agent( dest_port,
- snmp_check_packet,
- snmp_check_parse );
- if( ret != 0 )
- {
- snmp_trace ("Create socket failn");
- return 0;
- }
- init_start_time ();
- memset(addrCache, 0, sizeof(addrCache));
- /*
- * Forever monitor the dest_port for incoming PDUs.
- */
- init_mib_system();
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID, 0);
- output_error = 0;
- set_trapd_session_ptr();
- init_trap_retry_timer();
- return 0;
- } /* End main() -- snmpd */
- /*******************************************************************-o-******
- * receive
- *
- * Parameters:
- *
- * Returns:
- * 0 On success.
- * -1 System error.
- *
- * Infinite while-loop which monitors incoming messges for the agent.
- * Invoke the established message handlers for incoming messages on a per
- * port basis. Handle timeouts.
- */
- int
- receive(void)
- {
- int numfds;
- fd_set fdset;
- struct timeval timeout, *tvp;
- struct timeval sched, *svp = &sched,
- now, *nvp = &now;
- int count, block;
- #ifdef USING_SMUX_MODULE
- int i, sd;
- #endif /* USING_SMUX_MODULE */
- /*
- * Set the 'sched'uled timeout to the current time + one TIMETICK.
- */
- gettimeofday(nvp, (struct timezone *) NULL);
- svp->tv_usec = nvp->tv_usec + TIMETICK;
- svp->tv_sec = nvp->tv_sec;
- while (svp->tv_usec >= ONE_SEC){
- svp->tv_usec -= ONE_SEC;
- svp->tv_sec++;
- }
- /*
- * Loop-forever: execute message handlers for sockets with data,
- * reset the 'sched'uler.
- */
- while (running) {
- tvp = &timeout;
- tvp->tv_sec = 0;
- tvp->tv_usec = TIMETICK;
- numfds = 0;
- FD_ZERO(&fdset);
- block = 0;
- /* snmp_select_info(&numfds, &fdset, tvp, &block);*/
- snmp_sess_select_info(NULL, &numfds, &fdset, tvp, &block);
- if (block == 1)
- tvp = NULL; /* block without timeout */
- #ifdef USING_SMUX_MODULE
- if (smux_listen_sd >= 0) {
- FD_SET(smux_listen_sd, &fdset);
- numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds;
- for (i = 0; i < sdlen; i++) {
- FD_SET(sdlist[i], &fdset);
- numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds;
- }
- }
- #endif /* USING_SMUX_MODULE */
- count = so_select(numfds, &fdset, 0, 0, tvp);
- if (count > 0){
- snmp_read(&fdset);
- } else switch(count){
- case 0:
- snmp_timeout();
- break;
- case -1:
- tm_wkafter(1);
- break;
- /* if (errno == EINTR){
- continue;
- } else {
- snmp_trace("socket select err");
- }
- return -1;*/
- default:
- snmp_trace("select returned %dn", count);
- /*return -1;*/
- tm_wkafter(1);
- break;
- } /* endif -- count>0 */
- #ifdef USING_SMUX_MODULE
- /* handle the SMUX sd's */
- if (smux_listen_sd >= 0) {
- for (i = 0; i < sdlen; i++) {
- if (FD_ISSET(sdlist[i], &fdset)) {
- if (smux_process(sdlist[i]) < 0) {
- for (; i < (sdlen - 1); i++) {
- sdlist[i] = sdlist[i+1];
- }
- sdlen--;
- }
- }
- }
- /* new connection */
- if (FD_ISSET(smux_listen_sd, &fdset)) {
- if ((sd = smux_accept(smux_listen_sd)) >= 0) {
- sdlist[sdlen++] = sd;
- }
- }
- }
- #endif /* USING_SMUX_MODULE */
- /*
- * If the time 'now' is greater than the 'sched'uled time, then:
- *
- * Check alarm and event timers.
- * Reset the 'sched'uled time to current time + one TIMETICK.
- * Age the cache network addresses (from whom messges have
- * been received).
- */
- gettimeofday(nvp, (struct timezone *) NULL);
- if (nvp->tv_sec > svp->tv_sec
- || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
- svp->tv_usec = nvp->tv_usec + TIMETICK;
- svp->tv_sec = nvp->tv_sec;
- while (svp->tv_usec >= ONE_SEC){
- svp->tv_usec -= ONE_SEC;
- svp->tv_sec++;
- }
- if (log_addresses && lastAddrAge++ > 600){
- lastAddrAge = 0;
- for(count = 0; count < ADDRCACHE; count++){
- if (addrCache[count].status == OLD)
- addrCache[count].status = UNUSED;
- if (addrCache[count].status == USED)
- addrCache[count].status = OLD;
- }
- }
- } /* endif -- now>sched */
- /* run requested alarms */
- run_alarms();
- } /* endwhile */
- snmp_trace("Received TERM or STOP signal... shutting down...n");
- return 0;
- } /* end receive() */
- /*******************************************************************-o-******
- * snmp_check_packet
- *
- * Parameters:
- * session, from
- *
- * Returns:
- * 1 On success.
- * 0 On error.
- *
- * Handler for all incoming messages (a.k.a. packets) for the agent. If using
- * the libwrap utility, log the connection and deny/allow the access. Print
- * output when appropriate, and increment the incoming counter.
- *
- */
- int
- snmp_check_packet(struct snmp_session *session,
- struct soaddr from)
- {
- struct soaddr_in *fromIp = (struct soaddr_in *)&from;
- #ifdef USE_LIBWRAP
- const char *addr_string;
- /*
- * Log the message and/or dump the message.
- * Optionally cache the network address of the sender.
- */
- addr_string = inet_ntoa(fromIp->sin_addr);
- if(!addr_string) {
- addr_string = STRING_UNKNOWN;
- }
- if(hosts_ctl("snmpd", addr_string, addr_string, STRING_UNKNOWN)) {
- snmp_trace( "Connection from %sn", addr_string);
- } else {
- snmp_trace("Connection from %s REFUSEDn", addr_string);
- return(0);
- }
- #endif /* USE_LIBWRAP */
- snmp_increment_statistic(STAT_SNMPINPKTS);
- if (log_addresses || ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)){
- int count;
- for(count = 0; count < ADDRCACHE; count++){
- if (addrCache[count].status > UNUSED /* used or old */
- && fromIp->sin_addr.s_addr == addrCache[count].addr)
- break;
- }
- if (count >= ADDRCACHE ||
- ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)){
- snmp_trace("nReceived SNMP packet(s) from %sn",
- inet_ntoa(fromIp->sin_addr));
- for(count = 0; count < ADDRCACHE; count++){
- if (addrCache[count].status == UNUSED){
- addrCache[count].addr = fromIp->sin_addr.s_addr;
- addrCache[count].status = USED;
- break;
- }
- }
- } else {
- addrCache[count].status = USED;
- }
- }
- return ( 1 );
- }
- int snmp_get_do_logging (void)
- {
- return 0;
- }
- int
- snmp_check_parse( struct snmp_session *session,
- struct snmp_pdu *pdu,
- int result)
- {
- if ( result == 0 ) {
- if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))
- {
- char c_oid [SPRINT_MAX_LEN];
- struct variable_list *var_ptr;
- switch (pdu->command) {
- case SNMP_MSG_GET:
- snmp_trace(" SNMP: GET requestn"); break;
- case SNMP_MSG_GETNEXT:
- snmp_trace(" SNMP: GETNEXT requestn"); break;
- case SNMP_MSG_RESPONSE:
- snmp_trace(" SNMP: RESPONSE messagen"); break;
- case SNMP_MSG_SET:
- snmp_trace(" SNMP: SET requestn"); break;
- case SNMP_MSG_TRAP:
- snmp_trace(" SNMP: TRAP messagen"); break;
- case SNMP_MSG_GETBULK:
- snmp_trace(" SNMP: GETBULK request, non-rep=%d, max_rep=%dn",
- pdu->errstat, pdu->errindex); break;
- case SNMP_MSG_INFORM:
- snmp_trace(" SNMP: INFORM messagen"); break;
- case SNMP_MSG_TRAP2:
- snmp_trace(" SNMP: TRAP2 messagen"); break;
- case SNMP_MSG_REPORT:
- snmp_trace(" SNMP: REPORT messagen"); break;
- }
- for ( var_ptr = pdu->variables ;
- var_ptr != NULL ; var_ptr=var_ptr->next_variable )
- {
- sprint_objid (c_oid, var_ptr->name, var_ptr->name_length);
- snmp_trace(" -- %sn", c_oid);
- }
- }
- return 1;
- }
- return 0; /* XXX: does it matter what the return value is? */
- }
- /*******************************************************************-o-******
- * snmp_input
- *
- * Parameters:
- * op
- * *session
- * requid
- * *pdu
- * *magic
- *
- * Returns:
- * 1 On success -OR-
- * Passes through Return from alarmGetResponse() when
- * USING_V2PARTY_ALARM_MODULE is defined.
- *
- * Call-back function to manage responses to traps (informs) and alarms.
- * Not used by the agent to process other Response PDUs.
- */
- int
- snmp_input(int op,
- struct snmp_session *session,
- int reqid,
- struct snmp_pdu *pdu,
- void *magic)
- {
- struct get_req_state *state = (struct get_req_state *)magic;
- if (op == RECEIVED_MESSAGE) {
- if (pdu->command == SNMP_MSG_GET) {
- if (state->type == EVENT_GET_REQ) {
- /* this is just the ack to our inform pdu */
- return 1;
- }
- }
- }
- else if (op == TIMED_OUT) {
- if (state->type == ALARM_GET_REQ) {
- /* Need a mechanism to replace obsolete SNMPv2p alarm */
- }
- }
- return 1;
- } /* end snmp_input() */