snmpd.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,039 行 · 第 1/2 页

C
1,039
字号
                case 'A':                    dont_zero_log = 1;                    break;#if HAVE_UNISTD_H                case 'u':                  if (++arg == argc) usage(argv[0]);                  uid = atoi(argv[arg]);                  break;                case 'g':                  if (++arg == argc) usage(argv[0]);                  gid = atoi(argv[arg]);                  break;#endif                case 'h':                  usage(argv[0]);                  break;                case 'H':                  init_agent("snmpd");   /* register our .conf handlers */                  init_mib_modules();                  init_snmp("snmpd");                  fprintf(stderr, "Configuration directives understood:\n");                  read_config_print_usage("  ");                  exit(0);                case 'v':                  printf("\nUCD-snmp version:  %s\n",VersionInfo);                  printf("Author:            Wes Hardaker\n");                  printf("Email:             ucd-snmp-coders@ucd-snmp.ucdavis.edu\n\n");                  exit (0);                case '-':                  switch(argv[arg][2]){                    case 'v':                       printf("\nUCD-snmp version:  %s\n",VersionInfo);                      printf("Author:            Wes Hardaker\n");                      printf("Email:             ucd-snmp-coders@ucd-snmp.ucdavis.edu\n\n");                      exit (0);                    case 'h':                      usage(argv[0]);                      exit(0);                  }                default:                  printf("invalid option: %s\n", argv[arg]);                  usage(argv[0]);                  break;              }              continue;            }	}  /* end-for */	/* 	 * Initialize a argv set to the current for restarting the agent.	 */	argvrestartp = (char **) malloc((argc + 2) * sizeof(char *));	argvptr = argvrestartp;	for (i = 0, ret = 1; i < argc; i++) {		ret += strlen(argv[i]) + 1;	}	argvrestart = (char *) malloc(ret);	argvrestartname = (char *) malloc(strlen(argv[0]) + 1);	strcpy(argvrestartname, argv[0]);	if ( strstr(argvrestartname, "agentxd") != NULL)          ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, SUB_AGENT);	else          ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, MASTER_AGENT);	for (cptr = argvrestart, i = 0; i < argc; i++) {		strcpy(cptr, argv[i]);		*(argvptr++) = cptr;		cptr += strlen(argv[i]) + 1;	}	*cptr = 0;	*argvptr = NULL;	/* 	 * Open the logfile if necessary.	 */	/* Should open logfile and/or syslog based on arguments */	if (logfile[0])		snmp_enable_filelog(logfile, dont_zero_log);	if (syslog_log)		snmp_enable_syslog(); #ifdef BUFSIZ	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);#endif    /*      * Initialize the world.  Detach from the shell.     * Create initial user.     */#if HAVE_FORK    if (!dont_fork && fork() != 0) {      exit(0);    }#endif#if HAVE_GETPID    if (pid_file != NULL) {      if ((PID = fopen(pid_file, "w")) == NULL) {        snmp_log_perror("fopen");        if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS))          exit(1);      }      else {        fprintf(PID, "%d\n", (int)getpid());        fclose(PID);      }    }#endif#else /* __ECOS environment: */void snmpd( void *initfunc( void ) ) {    int             ret;    u_short         dest_port = SNMP_PORT;#define stderr_log 1#endif    // ---------    // En-bloc reinitialization of statics.    running = 1;    // ---------    SOCK_STARTUP;    init_agent("snmpd");		/* do what we need to do first. */    init_mib_modules();        /* start library */    init_snmp("snmpd");    ret = init_master_agent( dest_port,                       snmp_check_packet,                       snmp_check_parse );	if( ret != 0 )		Exit(1); /* Exit logs exit val for us */#ifdef SIGTERM    signal(SIGTERM, SnmpdShutDown);#endif#ifdef SIGINT    signal(SIGINT, SnmpdShutDown);#endif#ifdef SIGHUP    signal(SIGHUP, SnmpdReconfig);#endif#ifdef SIGUSR1    signal(SIGUSR1, SnmpdDump);#endif    /* send coldstart trap via snmptrap(1) if possible */    send_easy_trap (0, 0);        #if HAVE_UNISTD_H	if (gid) {		DEBUGMSGTL(("snmpd", "Changing gid to %d.\n", gid));		if (setgid(gid)==-1) {			snmp_log_perror("setgid failed");        		if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS))			  exit(1);		}	}	if (uid) {		DEBUGMSGTL(("snmpd", "Changing uid to %d.\n", uid));		if(setuid(uid)==-1) {			snmp_log_perror("setuid failed");        		if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS))			  exit(1);		}	}#endif	/* honor selection of standard error output */	if (!stderr_log)		snmp_disable_stderrlog();	/* we're up, log our version number */	snmp_log(LOG_INFO, "UCD-SNMP version %s\n", VersionInfo);	memset(addrCache, 0, sizeof(addrCache));        /*         * Call initialization function if necessary         */	DEBUGMSGTL(("snmpd", "Calling initfunc().\n"));        if ( initfunc )            (initfunc)();	/* 	 * Forever monitor the dest_port for incoming PDUs.	 */	DEBUGMSGTL(("snmpd", "We're up.  Starting to process data.\n"));	receive();#include "mib_module_shutdown.h"	DEBUGMSGTL(("snmpd", "sending shutdown trap\n"));	SnmpTrapNodeDown();	DEBUGMSGTL(("snmpd", "Bye...\n"));	snmp_shutdown("snmpd");}  /* 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. */	static intreceive(void){    int numfds;    fd_set fdset;    struct timeval	timeout, *tvp = &timeout;    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) {        if (reconfig) {          reconfig = 0;          snmp_log(LOG_INFO, "Reconfiguring daemon\n");          update_config();        }	tvp =  &timeout;	tvp->tv_sec = 0;	tvp->tv_usec = TIMETICK;	numfds = 0;	FD_ZERO(&fdset);        block = 0;        snmp_select_info(&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 = select(numfds, &fdset, 0, 0, tvp);	if (count > 0){	    snmp_read(&fdset);	} else switch(count){	    case 0:                snmp_timeout();                break;	    case -1:		if (errno == EINTR){		    continue;		} else {                    snmp_log_perror("select");		}		return -1;	    default:		snmp_log(LOG_ERR, "select returned %d\n", count);		return -1;	}  /* 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_log(LOG_INFO, "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. * */intsnmp_check_packet(struct snmp_session *session,  snmp_ipaddr from){    struct sockaddr_in *fromIp = (struct sockaddr_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_log(allow_severity, "Connection from %s\n", addr_string);    } else {      snmp_log(deny_severity, "Connection from %s REFUSED\n", 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_log(LOG_INFO, "Received SNMP packet(s) from %s\n",                        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 );}intsnmp_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) &&             snmp_get_do_logging() ) {	     char c_oid [SPRINT_MAX_LEN];	     struct variable_list *var_ptr;	    	    switch (pdu->command) {	    case SNMP_MSG_GET:	    	snmp_log(LOG_DEBUG, "  GET message\n"); break;	    case SNMP_MSG_GETNEXT:	    	snmp_log(LOG_DEBUG, "  GETNEXT message\n"); break;	    case SNMP_MSG_RESPONSE:	    	snmp_log(LOG_DEBUG, "  RESPONSE message\n"); break;	    case SNMP_MSG_SET:	    	snmp_log(LOG_DEBUG, "  SET message\n"); break;	    case SNMP_MSG_TRAP:	    	snmp_log(LOG_DEBUG, "  TRAP message\n"); break;	    case SNMP_MSG_GETBULK:	    	snmp_log(LOG_DEBUG, "  GETBULK message, non-rep=%d, max_rep=%d\n",			pdu->errstat, pdu->errindex); break;	    case SNMP_MSG_INFORM:	    	snmp_log(LOG_DEBUG, "  INFORM message\n"); break;	    case SNMP_MSG_TRAP2:	    	snmp_log(LOG_DEBUG, "  TRAP2 message\n"); break;	    case SNMP_MSG_REPORT:	    	snmp_log(LOG_DEBUG, "  REPORT message\n"); 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_log(LOG_DEBUG, "    -- %s\n", 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. */intsnmp_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() */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?