⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snmpd.c

📁 嵌入式操作系统ECOS的网络开发包
💻 C
📖 第 1 页 / 共 2 页
字号:

                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 int
receive(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.
 *
 */
int
snmp_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 );
}


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) &&
             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.
 */
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() */

⌨️ 快捷键说明

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