📄 snmpd.c
字号:
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 + -