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 + -
显示快捷键?