void init_kmem(const char *file) { kmem = open(file, O_RDONLY); if (kmem < 0 && !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log_perror(file); exit(1); } fcntl(kmem, F_SETFD, 1); mem = open("/dev/mem", O_RDONLY); if (mem < 0 && !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log_perror("/dev/mem"); exit(1); } fcntl(mem, F_SETFD, 1); #ifdef DMEM_LOC swap = open(DMEM_LOC, O_RDONLY); if (swap < 0 && !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log_perror(DMEM_LOC); exit(1); } fcntl(swap, F_SETFD, 1); #endif }
void do_something_perlish(char *something) { if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISABLE_PERL)) { return; } maybe_source_perl_startup(); if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISABLE_PERL)) { return; } DEBUGMSGTL(("perl", "calling perl\n")); #if defined(HAVE_EVAL_PV) || defined(eval_pv) /* newer perl */ eval_pv(something, TRUE); #else #if defined(HAVE_PERL_EVAL_PV_LC) || defined(perl_eval_pv) /* older perl? */ perl_eval_pv(something, TRUE); #else /* HAVE_PERL_EVAL_PV_LC */ #ifdef HAVE_PERL_EVAL_PV_UC /* older perl? */ Perl_eval_pv(my_perl, something, TRUE); #else /* !HAVE_PERL_EVAL_PV_UC */ #error embedded perl broken #endif /* !HAVE_PERL_EVAL_PV_LC */ #endif /* !HAVE_PERL_EVAL_PV_UC */ #endif /* !HAVE_EVAL_PV */ DEBUGMSGTL(("perl", "finished calling perl\n")); }
/** * Initialize the support for accessing kernel virtual memory. * * @return TRUE upon success; FALSE upon failure. */ int init_kmem (const char *file) { kmem = open (file, O_RDONLY); if (kmem < 0 && !netsnmp_ds_get_boolean (NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log_perror (file); } if (kmem >= 0) fcntl (kmem, F_SETFD, 1 /*FD_CLOEXEC */ ); mem = open ("/dev/mem", O_RDONLY); if (mem < 0 && !netsnmp_ds_get_boolean (NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log_perror ("/dev/mem"); } if (mem >= 0) fcntl (mem, F_SETFD, 1 /*FD_CLOEXEC */ ); #ifdef DMEM_LOC swap = open (DMEM_LOC, O_RDONLY); if (swap < 0 && !netsnmp_ds_get_boolean (NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log_perror (DMEM_LOC); } if (swap >= 0) fcntl (swap, F_SETFD, 1 /*FD_CLOEXEC */ ); #endif return kmem >= 0 && mem >= 0 && swap >= 0; }
int vacm_warn_if_not_configured(int majorID, int minorID, void *serverarg, void *clientarg) { const char * name = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE); const int agent_mode = netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE); if (NULL==name) name = "snmpd"; if (!vacm_is_configured()) { /* * An AgentX subagent relies on the master agent to apply suitable * access control checks, so doesn't need local VACM configuration. * The trap daemon has a separate check (see below). * * Otherwise, an AgentX master or SNMP standalone agent requires some * form of VACM configuration. No config means that no incoming * requests will be accepted, so warn the user accordingly. */ if ((MASTER_AGENT == agent_mode) && (strcmp(name, "snmptrapd") != 0)) { snmp_log(LOG_WARNING, "Warning: no access control information configured.\n" " (Config search path: %s)\n" " It's unlikely this agent can serve any useful purpose in this state.\n" " Run \"snmpconf -g basic_setup\" to help you " "configure the %s.conf file for this agent.\n", get_configuration_directory(), name); } /* * The trap daemon implements VACM-style access control for incoming * notifications, but offers a way of turning this off (for backwards * compatability). Check for this explicitly, and warn if necessary. * * NB: The NETSNMP_DS_APP_NO_AUTHORIZATION definition is a duplicate * of an identical setting in "apps/snmptrapd_ds.h". * These two need to be kept in synch. */ #ifndef NETSNMP_DS_APP_NO_AUTHORIZATION #define NETSNMP_DS_APP_NO_AUTHORIZATION 17 #endif if (!strcmp(name, "snmptrapd") && !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_NO_AUTHORIZATION)) { snmp_log(LOG_WARNING, "Warning: no access control information configured.\n" " (Config search path: %s)\n" "This receiver will *NOT* accept any incoming notifications.\n", get_configuration_directory()); } } return SNMP_ERR_NOERROR; }
int netsnmp_transport_send(netsnmp_transport *t, void *packet, int length, void **opaque, int *olength) { int dumpPacket, debugLength; if ((NULL == t) || (NULL == t->f_send)) { DEBUGMSGTL(("transport:pkt:send", "NULL transport or send function\n")); return SNMPERR_GENERR; } dumpPacket = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET); debugLength = (SNMPERR_SUCCESS == debug_is_token_registered("transport:send")); if (dumpPacket | debugLength) { char *str = netsnmp_transport_peer_string(t, opaque ? *opaque : NULL, olength ? *olength : 0); if (debugLength) DEBUGMSGT_NC(("transport:send","%lu bytes to %s\n", (unsigned long)length, str)); if (dumpPacket) snmp_log(LOG_DEBUG, "\nSending %lu bytes to %s\n", (unsigned long)length, str); SNMP_FREE(str); } if (dumpPacket) xdump(packet, length, ""); return t->f_send(t, packet, length, opaque, olength); }
/** * init subagent callback (local) session and connect to master agent * * @returns 0 for success, !0 otherwise */ int subagent_init (void) { int rc = 0; DEBUGMSGTL (("agentx/subagent", "initializing....\n")); if (++subagent_init_init != 1) return 0; netsnmp_assert (netsnmp_ds_get_boolean (NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT); #ifndef NETSNMP_TRANSPORT_CALLBACK_DOMAIN snmp_log (LOG_WARNING, "AgentX subagent has been disabled because " "the callback transport is not available.\n"); return -1; #endif /* NETSNMP_TRANSPORT_CALLBACK_DOMAIN */ /* * open (local) callback session */ subagent_init_callback_session (); if (NULL == agentx_callback_sess) return -1; snmp_register_callback (SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, subagent_startup, NULL); DEBUGMSGTL (("agentx/subagent", "initializing.... DONE\n")); return rc; }
void init_agentx_config(void) { /* * Don't set this up as part of the per-module initialisation. * Delay this until the 'init_master_agent()' routine is called, * so that the config settings have been processed. * This means that we can use a config directive to determine * whether or not to run as an AgentX master. */ #ifdef USING_AGENTX_MASTER_MODULE if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == MASTER_AGENT) snmpd_register_config_handler("master", agentx_parse_master, NULL, "specify 'agentx' for AgentX support"); #endif /* USING_AGENTX_MASTER_MODULE */ snmpd_register_config_handler("agentxsocket", agentx_parse_agentx_socket, NULL, "AgentX bind address"); snmpd_register_config_handler("agentxperms", agentx_parse_agentx_perms, NULL, "AgentX socket permissions: socket_perms [directory_perms [username|userid [groupname|groupid]]]"); snmpd_register_config_handler("agentxRetries", agentx_parse_agentx_retries, NULL, "AgentX Retries"); snmpd_register_config_handler("agentxTimeout", agentx_parse_agentx_timeout, NULL, "AgentX Timeout (seconds)"); }
/* * returns non-zero on error */ int subagent_pre_init(void) { DEBUGMSGTL(("agentx/subagent", "initializing....\n")); /* * set up callbacks to initiate master agent pings for this session */ netsnmp_ds_register_config(ASN_INTEGER, netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE), "agentxPingInterval", NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL); if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) != SUB_AGENT) { return 0; } /* * if a valid ping interval has been defined, call agentx_reopen_session * * to try to connect to master or setup a ping alarm if it couldn't * * succeed */ if (netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL) > 0) agentx_reopen_session(0, NULL); else /* if no ping interval was set up, just try to connect once */ subagent_open_master_session(); if (!main_session) return -1; DEBUGMSGTL(("agentx/subagent", "initializing.... DONE\n")); return 0; }
int verify_callback(int ok, X509_STORE_CTX *ctx) { int err, depth; char buf[1024]; X509 *thecert; thecert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); /* things to do: */ X509_NAME_oneline(X509_get_subject_name(thecert), buf, sizeof(buf)); DEBUGMSGTL(("dtlsudp_x509", "Cert: %s\n", buf)); DEBUGMSGTL(("dtlsudp_x509", " verify value: %d, depth=%d, error code=%d, error string=%s\n", ok, depth, err, _x509_get_error(err, "verify callback"))); /* check if we allow self-signed certs */ if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ALLOW_SELF_SIGNED) && (X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT == err || X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN == err)) { DEBUGMSGTL(("dtlsudp_x509", " accepting a self-signed certificate\n")); return 1; } DEBUGMSGTL(("dtlsudp_x509", " returing the passed in value of %d\n", ok)); return(ok); }
int is_excluded(const char *name) { if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISKIO_NO_FD) && !(strncmp(name, "fd", 2))) return 1; if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISKIO_NO_LOOP) && !(strncmp(name, "loop", 4))) return 1; if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISKIO_NO_RAM) && !(strncmp(name, "ram", 3))) return 1; return 0; }
int log_handler_stdouterr( netsnmp_log_handler* logh, int pri, const char *str) { static int newline = 1; /* MTCRITICAL_RESOURCE */ const char *newline_ptr; char sbuf[40]; if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_LOG_TIMESTAMP) && newline) { sprintf_stamp(NULL, sbuf); } else { strcpy(sbuf, ""); } /* * Remember whether or not the current line ends with a newline for the * next call of log_handler_stdouterr(). */ newline_ptr = strrchr(str, '\n'); newline = newline_ptr && newline_ptr[1] == 0; if (logh->imagic) printf( "%s%s", sbuf, str); else fprintf(stderr, "%s%s", sbuf, str); return 1; }
void agentx_config_init(void) { int agent_role = netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE); /* * Common tokens for master/subagent */ netsnmp_register_default_domain("agentx", "unix tcp"); netsnmp_register_default_target("agentx", "unix", NETSNMP_AGENTX_SOCKET); #define val(x) __STRING(x) netsnmp_register_default_target("agentx", "tcp", "localhost:" val(AGENTX_PORT)); #undef val agentx_register_config_handler("agentxsocket", agentx_parse_agentx_socket, NULL, "AgentX bind address"); #ifdef USING_AGENTX_MASTER_MODULE /* * tokens for master agent */ if (MASTER_AGENT == agent_role) { snmpd_register_config_handler("master", agentx_parse_master, NULL, "specify 'agentx' for AgentX support"); agentx_register_config_handler("agentxperms", agentx_parse_agentx_perms, NULL, "AgentX socket permissions: socket_perms [directory_perms [username|userid [groupname|groupid]]]"); agentx_register_config_handler("agentxRetries", agentx_parse_agentx_retries, NULL, "AgentX Retries"); agentx_register_config_handler("agentxTimeout", agentx_parse_agentx_timeout, NULL, "AgentX Timeout (seconds)"); } #endif /* USING_AGENTX_MASTER_MODULE */ #ifdef USING_AGENTX_SUBAGENT_MODULE /* * tokens for master agent */ if (SUB_AGENT == agent_role) { /* * set up callbacks to initiate master agent pings for this session */ netsnmp_ds_register_config(ASN_INTEGER, netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE), "agentxPingInterval", NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL); /* ping and/or reconnect by default every 15 seconds */ netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL, 15); } #endif /* USING_AGENTX_SUBAGENT_MODULE */ }
int handle_nsDebugDumpPdu(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { long enabled; netsnmp_request_info *request=NULL; switch (reqinfo->mode) { case MODE_GET: enabled = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET); if ( enabled==0 ) enabled=2; /* false */ for (request = requests; request; request=request->next) { if (request->processed != 0) continue; snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, (u_char*)&enabled, sizeof(enabled)); } break; #ifndef NETSNMP_NO_WRITE_SUPPORT case MODE_SET_RESERVE1: for (request = requests; request; request=request->next) { if (request->processed != 0) continue; if ( request->status != 0 ) { return SNMP_ERR_NOERROR; /* Already got an error */ } if ( request->requestvb->type != ASN_INTEGER ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); return SNMP_ERR_WRONGTYPE; } if (( *request->requestvb->val.integer != 1 ) && ( *request->requestvb->val.integer != 2 )) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); return SNMP_ERR_WRONGVALUE; } } break; case MODE_SET_COMMIT: enabled = *requests->requestvb->val.integer; if (enabled == 2 ) /* false */ enabled = 0; netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET, enabled); break; #endif /* !NETSNMP_NO_WRITE_SUPPORT */ } return SNMP_ERR_NOERROR; }
int handle_nsCacheEnabled(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { long enabled; netsnmp_request_info *request=NULL; switch (reqinfo->mode) { case MODE_GET: enabled = (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CACHING) ? NSCACHE_STATUS_ENABLED /* Actually True/False */ : NSCACHE_STATUS_DISABLED ); for (request = requests; request; request=request->next) { snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, (u_char*)&enabled, sizeof(enabled)); } break; #ifndef NETSNMP_NO_WRITE_SUPPORT case MODE_SET_RESERVE1: for (request = requests; request; request=request->next) { if ( request->status != 0 ) { return SNMP_ERR_NOERROR; /* Already got an error */ } if ( request->requestvb->type != ASN_INTEGER ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); return SNMP_ERR_WRONGTYPE; } if ((*request->requestvb->val.integer != NSCACHE_STATUS_ENABLED) && (*request->requestvb->val.integer != NSCACHE_STATUS_DISABLED)) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); return SNMP_ERR_WRONGVALUE; } } break; case MODE_SET_COMMIT: enabled = *requests->requestvb->val.integer; if (enabled == NSCACHE_STATUS_DISABLED) enabled = 0; netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CACHING, enabled); break; #endif /* !NETSNMP_NO_WRITE_SUPPORT */ } return SNMP_ERR_NOERROR; }
void init_kmem(const char *file) { #if HAVE_KVM_OPENFILES char err[4096]; kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, err); if (kd == NULL && !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log(LOG_CRIT, "init_kmem: kvm_openfiles failed: %s\n", err); exit(1); } #else kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); if (!kd && !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { snmp_log(LOG_CRIT, "init_kmem: kvm_open failed: %s\n", strerror(errno)); exit(1); } #endif /* HAVE_KVM_OPENFILES */ }
void shutdown_perl(void) { if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISABLE_PERL)) { return; } DEBUGMSGTL(("perl", "shutting down perl\n")); perl_destruct(my_perl); perl_free(my_perl); DEBUGMSGTL(("perl", "finished shutting down perl\n")); }
/* to do: make sure diskio_free_config() gets invoked upon SIGHUP. */ static int diskio_free_config(int major, int minor, void *serverarg, void *clientarg) { DEBUGMSGTL(("diskio", "free config %d\n", netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISKIO_NO_RAM))); netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISKIO_NO_FD, 0); netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISKIO_NO_LOOP, 0); netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_DISKIO_NO_RAM, 0); return 0; }
struct hostent * netsnmp_gethostbyname(const char *name) { #if HAVE_GETHOSTBYNAME #ifdef DNSSEC_LOCAL_VALIDATION val_status_t val_status; #endif struct hostent *hp = NULL; if (NULL == name) return NULL; DEBUGMSGTL(("dns:gethostbyname", "looking up %s\n", name)); #ifdef DNSSEC_LOCAL_VALIDATION hp = val_gethostbyname(netsnmp_validator_context(), name, &val_status); DEBUGMSGTL(("dns:sec:val", "val_status %d / %s; trusted: %d\n", val_status, p_val_status(val_status), val_istrusted(val_status))); if (!val_istrusted(val_status)) { snmp_log(LOG_WARNING, "The authenticity of DNS response is not trusted (%s)\n", p_val_status(val_status)); /** continue anyways if DNSSEC_WARN_ONLY is set */ if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DNSSEC_WARN_ONLY)) hp = NULL; } else if (val_does_not_exist(val_status) && hp) hp = NULL; #else hp = gethostbyname(name); #endif if (hp == NULL) { DEBUGMSGTL(("dns:gethostbyname", "couldn't resolve %s\n", name)); } else if (hp->h_addrtype != AF_INET) { DEBUGMSGTL(("dns:gethostbyname", "warning: response for %s not AF_INET!\n", name)); } else { DEBUGMSGTL(("dns:gethostbyname", "%s resolved okay\n", name)); } return hp; #else NETSNMP_LOGONCE((LOG_ERR, "gethostbyname not available")); return NULL; #endif /* HAVE_GETHOSTBYNAME */ }
/** * Checks to see if the pdu is authorized for a set of given action types. * @returns 1 if authorized, 0 if not. */ int netsnmp_trapd_check_auth(int authtypes) { if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_NO_AUTHORIZATION)) { DEBUGMSGTL(("snmptrapd:auth", "authorization turned off\n")); return 1; } DEBUGMSGTL(("snmptrapd:auth", "Comparing auth types: result=%d, request=%d, result=%d\n", lastlookup, authtypes, ((authtypes & lastlookup) == authtypes))); return ((authtypes & lastlookup) == authtypes); }
struct hostent * netsnmp_gethostbyaddr(const void *addr, socklen_t len, int type) { #if HAVE_GETHOSTBYADDR struct hostent *hp = NULL; struct sockaddr_in *saddr_in = NETSNMP_REMOVE_CONST(struct sockaddr_in *,addr); DEBUGMSGTL(("dns:gethostbyaddr", "resolving { AF_INET, %s:%hu }\n", inet_ntoa(saddr_in->sin_addr), ntohs(saddr_in->sin_port))); #ifdef DNSSEC_LOCAL_VALIDATION val_status_t val_status; hp = val_gethostbyaddr(netsnmp_validator_context(), (const void*)&saddr_in->sin_addr, sizeof(struct in_addr), AF_INET, &val_status); DEBUGMSGTL(("dns:sec:val", "val_status %d / %s; trusted: %d\n", val_status, p_val_status(val_status), val_istrusted(val_status))); if (!val_istrusted(val_status)) { snmp_log(LOG_WARNING, "The authenticity of DNS response is not trusted (%s)\n", p_val_status(val_status)); /** continue anyways if DNSSEC_WARN_ONLY is set */ if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DNSSEC_WARN_ONLY)) hp = NULL; } else if (val_does_not_exist(val_status) && hp) hp = NULL; #else hp = gethostbyaddr((const void*) &saddr_in->sin_addr, sizeof(struct in_addr), AF_INET); #endif if (hp == NULL) { DEBUGMSGTL(("dns:gethostbyaddr", "couldn't resolve addr\n")); } else if (hp->h_addrtype != AF_INET) { DEBUGMSGTL(("dns:gethostbyaddr", "warning: response for addr not AF_INET!\n")); } else { DEBUGMSGTL(("dns:gethostbyaddr", "addr resolved okay\n")); } return hp; #else NETSNMP_LOGONCE((LOG_ERR, "gethostbyaddr not available")); return NULL; #endif }
static void setup_mib_flags(int resolve_oids) { #ifdef DEBUG /* snmp_set_mib_warnings (2); */ #endif /* DEBUG */ if (resolve_oids) { setenv ("MIBS", "ALL", 1); } #ifdef HAVE_NETSNMP_INIT_MIB netsnmp_init_mib (); #else init_mib (); #endif if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS); } /* we want OIDs to appear in numeric form */ if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM); } /* we want enums to appear in numeric form as integers */ if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID); } /* we want to full numeric OID to be printed, including prefix */ if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS); } if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS); } /* so we can use sysContact.0 instead of system.sysContact.0 */ if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS); } /* so we can use sysContact.0 instead of system.sysContact.0 */ }
netsnmp_log_handler * netsnmp_register_filelog_handler(const char* logfilename, int priority, int priority_max, int dont_zero_log) { netsnmp_log_handler *logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_FILE, priority ); if (NULL == logh) return NULL; logh->pri_max = priority_max; logh->token = strdup(logfilename); if (-1 == dont_zero_log) dont_zero_log = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPEND_LOGFILES); netsnmp_enable_filelog(logh, dont_zero_log); return logh; }
int log_handler_stdouterr( netsnmp_log_handler* logh, int pri, const char *str) { char sbuf[40]; if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_LOG_TIMESTAMP) && newline) { sprintf_stamp(NULL, sbuf); } else { strcpy(sbuf, ""); } newline = str[strlen(str) - 1] == '\n'; /* XXX - Eh ? */ if (logh->imagic) printf( "%s%s", sbuf, str); else fprintf(stderr, "%s%s", sbuf, str); return 1; }
int log_handler_file( netsnmp_log_handler* logh, int pri, const char *str) { FILE *fhandle; char sbuf[40]; /* * We use imagic to save information about whether the next output * will start a new line, and thus might need a timestamp */ if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_LOG_TIMESTAMP) && logh->imagic) { sprintf_stamp(NULL, sbuf); } else { strcpy(sbuf, ""); } /* * If we haven't already opened the file, then do so. * Save the filehandle pointer for next time. * * Note that this should still work, even if the file * is closed in the meantime (e.g. a regular "cleanup" sweep) */ fhandle = (FILE*)logh->magic; if (!logh->magic) { fhandle = fopen(logh->token, "a+"); if (!fhandle) return 0; logh->magic = (void*)fhandle; } fprintf(fhandle, "%s%s", sbuf, str); fflush(fhandle); logh->imagic = str[strlen(str) - 1] == '\n'; return 1; }
/** * Initialize the agent. Calls into init_agent_read_config to set tha app's * configuration file in the appropriate default storage space, * NETSNMP_DS_LIB_APPTYPE. Need to call init_agent before calling init_snmp. * * @param app the configuration file to be read in, gets stored in default * storage * * @return Returns non-zero on failure and zero on success. * * @see init_snmp */ int init_agent(const char *app) { int r = 0; if(++done_init_agent > 1) { snmp_log(LOG_WARNING, "ignoring extra call to init_agent (%d)\n", done_init_agent); return r; } /* * get current time (ie, the time the agent started) */ gettimeofday(&starttime, NULL); starttime.tv_sec--; starttime.tv_usec += 1000000L; /* * we handle alarm signals ourselves in the select loop */ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ALARM_DONT_USE_SIG, 1); #ifdef CAN_USE_NLIST init_kmem("/dev/kmem"); #endif setup_tree(); init_agent_read_config(app); #ifdef TESTING auto_nlist_print_tree(-2, 0); #endif _init_agent_callback_transport(); netsnmp_init_helpers(); init_traps(); netsnmp_container_init_list(); #if defined(USING_AGENTX_SUBAGENT_MODULE) || defined(USING_AGENTX_MASTER_MODULE) /* * initialize agentx configs */ agentx_config_init(); if(netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) subagent_init(); #endif /* * Register configuration tokens from transport modules. */ #ifdef SNMP_TRANSPORT_UDP_DOMAIN netsnmp_udp_agent_config_tokens_register(); #endif #ifdef SNMP_TRANSPORT_UDPIPV6_DOMAIN netsnmp_udp6_agent_config_tokens_register(); #endif #ifdef SNMP_TRANSPORT_UNIX_DOMAIN netsnmp_unix_agent_config_tokens_register(); #endif #ifdef NETSNMP_EMBEDDED_PERL init_perl(); #endif #ifdef USING_AGENTX_SUBAGENT_MODULE /* * don't init agent modules for a sub-agent */ if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) return r; #endif # include "agent_module_inits.h" return r; } /* end init_agent() */
void netsnmp_fsys_arch_load( void ) { int ret = 0; uint size = 0; struct vmount *aixmnt, *aixcurr; char *path; struct statfs stat_buf; netsnmp_fsys_info *entry; char tmpbuf[1024]; /* * Retrieve information about the currently mounted filesystems... */ ret = mntctl(MCTL_QUERY, sizeof(uint), &size); if ( ret != 0 || size<=0 ) { snmp_log_perror( "initial mntctl failed" ); return; } aixmnt = (struct vmount *)malloc( size ); if ( aixmnt == NULL ) { snmp_log_perror( "cannot allocate memory for mntctl data" ); return; } ret = mntctl(MCTL_QUERY, size, aixmnt ); if ( ret <= 0 ) { free(aixmnt); snmp_log_perror( "main mntctl failed" ); return; } aixcurr = aixmnt; /* * ... and insert this into the filesystem container. */ for ( aixcurr = aixmnt; (aixcurr-aixmnt) >= size; aixcurr = (char*)aixcurr + aixcurr->vmt_length ) { path = vmt2dataptr( aixcurr, VMT_OBJECT ); entry = netsnmp_fsys_by_path( path, NETSNMP_FS_FIND_CREATE ); if (!entry) { continue; } strncpy( entry->path, path, sizeof( entry->path )); strncpy( entry->device, vmt2dataptr( aixcurr, VMT_STUB), sizeof( entry->device )); entry->type = _fsys_type( aixcurr->vmt_gfstype ); if (!(entry->type & _NETSNMP_FS_TYPE_SKIP_BIT)) entry->flags |= NETSNMP_FS_FLAG_ACTIVE; if ( _fsys_remote( entry->device, entry->type, vmt2dataptr( aixcurr, VMT_HOST) )) entry->flags |= NETSNMP_FS_FLAG_REMOTE; if ( aixcurr->vmt_flags & MNT_READONLY ) entry->flags |= NETSNMP_FS_FLAG_RONLY; /* * The root device is presumably bootable. * Other partitions probably aren't! */ if ((entry->path[0] == '/') && (entry->path[1] == '\0')) entry->flags |= NETSNMP_FS_FLAG_BOOTABLE; /* * XXX - identify removeable disks */ /* * Optionally skip retrieving statistics for remote mounts */ if ( (entry->flags & NETSNMP_FS_FLAG_REMOTE) && netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_SKIPNFSINHOSTRESOURCES)) continue; if ( statfs( entry->path, &stat_buf ) < 0 ) { snprintf( tmpbuf, sizeof(tmpbuf), "Cannot statfs %s\n", entry->path ); snmp_log_perror( tmpbuf ); continue; } entry->units = stat_buf.f_bsize; entry->size = stat_buf.f_blocks; entry->used = (stat_buf.f_blocks - stat_buf.f_bfree); entry->avail = stat_buf.f_bavail; entry->inums_total = stat_buf.f_files; entry->inums_avail = stat_buf.f_ffree; netsnmp_fsys_calculate32(entry); } free(aixmnt); aixmnt = NULL; aixcurr = NULL; }
int unregister_index(netsnmp_variable_list * varbind, int remember, netsnmp_session * ss) { struct snmp_index *idxptr, *idxptr2; struct snmp_index *prev_oid_ptr, *prev_idx_ptr; int res, res2, i; #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING) if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) { return (agentx_unregister_index(ss, varbind)); } #endif /* * Look for the requested OID entry */ prev_oid_ptr = NULL; prev_idx_ptr = NULL; res = 1; res2 = 1; for (idxptr = snmp_index_head; idxptr != NULL; prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) { if ((res = snmp_oid_compare(varbind->name, varbind->name_length, idxptr->varbind->name, idxptr->varbind->name_length)) <= 0) break; } if (res != 0) return INDEX_ERR_NOT_ALLOCATED; if (varbind->type != idxptr->varbind->type) return INDEX_ERR_WRONG_TYPE; for (idxptr2 = idxptr; idxptr2 != NULL; prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { switch (varbind->type) { case ASN_INTEGER: res2 = (*varbind->val.integer - *idxptr2->varbind->val.integer); break; case ASN_OCTET_STR: i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len); res2 = memcmp(varbind->val.string, idxptr2->varbind->val.string, i); break; case ASN_OBJECT_ID: res2 = snmp_oid_compare(varbind->val.objid, varbind->val_len / sizeof(oid), idxptr2->varbind->val.objid, idxptr2->varbind->val_len / sizeof(oid)); break; default: return INDEX_ERR_WRONG_TYPE; /* wrong type */ } if (res2 <= 0) break; } if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) { return INDEX_ERR_NOT_ALLOCATED; } if (ss != idxptr2->session) return INDEX_ERR_WRONG_SESSION; /* * If this is a "normal" index unregistration, * mark the index entry as unused, but leave * it in situ. This allows differentiation * between ANY_INDEX and NEW_INDEX */ if (remember) { idxptr2->allocated = 0; /* Unused index */ idxptr2->session = NULL; return SNMP_ERR_NOERROR; } /* * If this is a failed attempt to register a * number of indexes, the successful ones * must be removed completely. */ if (prev_idx_ptr) { prev_idx_ptr->next_idx = idxptr2->next_idx; } else if (prev_oid_ptr) { if (idxptr2->next_idx) /* Use p_idx_ptr as a temp variable */ prev_idx_ptr = idxptr2->next_idx; else prev_idx_ptr = idxptr2->next_oid; while (prev_oid_ptr) { prev_oid_ptr->next_oid = prev_idx_ptr; prev_oid_ptr = prev_oid_ptr->next_idx; } } else { if (idxptr2->next_idx) snmp_index_head = idxptr2->next_idx; else snmp_index_head = idxptr2->next_oid; } snmp_free_var(idxptr2->varbind); free(idxptr2); return SNMP_ERR_NOERROR; }
main(int argc, char *argv[]) #endif { char options[128] = "aAc:CdD::fhHI:l:L:m:M:n:p:P:qrsS:UvV-:Y:"; int arg, i, ret; int dont_fork = 0, do_help = 0; int log_set = 0; int agent_mode = -1; char *pid_file = NULL; char option_compatability[] = "-Le"; #ifndef WIN32 int prepared_sockets = 0; #endif #if HAVE_GETPID int fd; FILE *PID; #endif #ifndef WIN32 #ifndef NETSNMP_NO_SYSTEMD /* check if systemd has sockets for us and don't close them */ prepared_sockets = netsnmp_sd_listen_fds(0); #endif /* NETSNMP_NO_SYSTEMD */ /* * close all non-standard file descriptors we may have * inherited from the shell. */ if (!prepared_sockets) { for (i = getdtablesize() - 1; i > 2; --i) { (void) close(i); } } #endif /* #WIN32 */ /* * register signals ASAP to prevent default action (usually core) * for signals during startup... */ #ifdef SIGTERM DEBUGMSGTL(("signal", "registering SIGTERM signal handler\n")); signal(SIGTERM, SnmpdShutDown); #endif #ifdef SIGINT DEBUGMSGTL(("signal", "registering SIGINT signal handler\n")); signal(SIGINT, SnmpdShutDown); #endif #ifdef SIGHUP signal(SIGHUP, SIG_IGN); /* do not terminate on early SIGHUP */ #endif #ifdef SIGUSR1 DEBUGMSGTL(("signal", "registering SIGUSR1 signal handler\n")); signal(SIGUSR1, SnmpdDump); #endif #ifdef SIGPIPE DEBUGMSGTL(("signal", "registering SIGPIPE signal handler\n")); signal(SIGPIPE, SIG_IGN); /* 'Inline' failure of wayward readers */ #endif #ifdef SIGXFSZ signal(SIGXFSZ, SnmpdCatchRandomSignal); #endif #ifdef NETSNMP_NO_ROOT_ACCESS /* * Default to no. */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1); #endif /* * Default to NOT running an AgentX master. */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_MASTER, 0); netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_TIMEOUT, -1); netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_RETRIES, -1); netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_CACHE_TIMEOUT, 5); /* * Add some options if they are available. */ #if HAVE_UNISTD_H strcat(options, "g:u:"); #endif #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE) strcat(options, "x:"); #endif #ifdef USING_AGENTX_SUBAGENT_MODULE strcat(options, "X"); #endif /* * This is incredibly ugly, but it's probably the simplest way * to handle the old '-L' option as well as the new '-Lx' style */ for (i=0; i<argc; i++) { if (!strcmp(argv[i], "-L")) argv[i] = option_compatability; } #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG #ifdef WIN32 snmp_log_syslogname(app_name_long); #else snmp_log_syslogname(app_name); #endif #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE, app_name); /* * Now process options normally. */ while ((arg = getopt(argc, argv, options)) != EOF) { switch (arg) { case '-': if (strcasecmp(optarg, "help") == 0) { usage(argv[0]); } if (strcasecmp(optarg, "version") == 0) { version(); } handle_long_opt(optarg); break; case 'a': log_addresses++; break; case 'A': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPEND_LOGFILES, 1); break; case 'c': if (optarg != NULL) { netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OPTIONALCONFIG, optarg); } else { usage(argv[0]); } break; case 'C': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1); break; case 'd': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET, ++snmp_dump_packet); break; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'f': dont_fork = 1; break; #if HAVE_UNISTD_H case 'g': if (optarg != NULL) { char *ecp; int gid; gid = strtoul(optarg, &ecp, 10); #if HAVE_GETGRNAM && HAVE_PWD_H if (*ecp) { struct group *info; info = getgrnam(optarg); gid = info ? info->gr_gid : -1; endgrent(); } #endif if (gid < 0) { fprintf(stderr, "Bad group id: %s\n", optarg); exit(1); } netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_GROUPID, gid); } else { usage(argv[0]); } break; #endif case 'h': usage(argv[0]); break; case 'H': do_help = 1; break; case 'I': if (optarg != NULL) { add_to_init_list(optarg); } else { usage(argv[0]); } break; #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_FILE case 'l': printf("Warning: -l option is deprecated, use -Lf <file> instead\n"); if (optarg != NULL) { if (strlen(optarg) > PATH_MAX) { fprintf(stderr, "%s: logfile path too long (limit %d chars)\n", argv[0], PATH_MAX); exit(1); } snmp_enable_filelog(optarg, netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPEND_LOGFILES)); log_set = 1; } else { usage(argv[0]); } break; #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_FILE */ case 'L': if (snmp_log_options( optarg, argc, argv ) < 0 ) { usage(argv[0]); } log_set = 1; break; case 'm': if (optarg != NULL) { setenv("MIBS", optarg, 1); } else { usage(argv[0]); } break; case 'M': if (optarg != NULL) { setenv("MIBDIRS", optarg, 1); } else { usage(argv[0]); } break; case 'n': if (optarg != NULL) { app_name = optarg; netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE, app_name); } else { usage(argv[0]); } break; case 'P': printf("Warning: -P option is deprecated, use -p instead\n"); case 'p': if (optarg != NULL) { pid_file = optarg; } else { usage(argv[0]); } break; case 'q': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, 1); break; case 'r': netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS); break; #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG case 's': printf("Warning: -s option is deprecated, use -Lsd instead\n"); snmp_enable_syslog(); log_set = 1; break; case 'S': printf("Warning: -S option is deprecated, use -Ls <facility> instead\n"); if (optarg != NULL) { switch (*optarg) { case 'd': case 'D': Facility = LOG_DAEMON; break; case 'i': case 'I': Facility = LOG_INFO; break; case '0': Facility = LOG_LOCAL0; break; case '1': Facility = LOG_LOCAL1; break; case '2': Facility = LOG_LOCAL2; break; case '3': Facility = LOG_LOCAL3; break; case '4': Facility = LOG_LOCAL4; break; case '5': Facility = LOG_LOCAL5; break; case '6': Facility = LOG_LOCAL6; break; case '7': Facility = LOG_LOCAL7; break; default: fprintf(stderr, "invalid syslog facility: -S%c\n",*optarg); usage(argv[0]); } snmp_enable_syslog_ident(snmp_log_syslogname(NULL), Facility); log_set = 1; } else { fprintf(stderr, "no syslog facility specified\n"); usage(argv[0]); } break; #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ case 'U': netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_LEAVE_PIDFILE); break; #if HAVE_UNISTD_H case 'u': if (optarg != NULL) { char *ecp; int uid; uid = strtoul(optarg, &ecp, 10); #if HAVE_GETPWNAM && HAVE_PWD_H if (*ecp) { struct passwd *info; info = getpwnam(optarg); uid = info ? info->pw_uid : -1; endpwent(); } #endif if (uid < 0) { fprintf(stderr, "Bad user id: %s\n", optarg); exit(1); } netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_USERID, uid); } else { usage(argv[0]); } break; #endif case 'v': version(); case 'V': netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_VERBOSE, 1); break; #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE) case 'x': if (optarg != NULL) { netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET, optarg); } else { usage(argv[0]); } netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_MASTER, 1); break; #endif case 'X': #if defined(USING_AGENTX_SUBAGENT_MODULE) agent_mode = SUB_AGENT; #else fprintf(stderr, "%s: Illegal argument -X:" "AgentX support not compiled in.\n", argv[0]); usage(argv[0]); exit(1); #endif break; case 'Y': netsnmp_config_remember(optarg); break; default: usage(argv[0]); break; } } if (do_help) { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1); init_agent(app_name); /* register our .conf handlers */ init_mib_modules(); init_snmp(app_name); fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage(" "); exit(0); } if (optind < argc) { #ifndef NETSNMP_NO_LISTEN_SUPPORT /* * There are optional transport addresses on the command line. */ DEBUGMSGTL(("snmpd/main", "optind %d, argc %d\n", optind, argc)); for (i = optind; i < argc; i++) { char *c, *astring; if ((c = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_PORTS))) { astring = (char*)malloc(strlen(c) + 2 + strlen(argv[i])); if (astring == NULL) { fprintf(stderr, "malloc failure processing argv[%d]\n", i); exit(1); } sprintf(astring, "%s,%s", c, argv[i]); netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_PORTS, astring); SNMP_FREE(astring); } else { netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_PORTS, argv[i]); } } DEBUGMSGTL(("snmpd/main", "port spec: %s\n", netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_PORTS))); #else /* NETSNMP_NO_LISTEN_SUPPORT */ fprintf(stderr, "You specified ports to open; this agent was built to only send notifications\n"); exit(1); #endif /* NETSNMP_NO_LISTEN_SUPPORT */ } #ifdef NETSNMP_LOGFILE #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_FILE if (0 == log_set) snmp_enable_filelog(NETSNMP_LOGFILE, netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPEND_LOGFILES)); #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_FILE */ #endif #ifdef USING_UTIL_FUNCS_RESTART_MODULE { /* * Initialize a argv set to the current for restarting the agent. */ char *cptr, **argvptr; 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); if (!argvrestartp || !argvrestart || !argvrestartname) { fprintf(stderr, "malloc failure processing argvrestart\n"); exit(1); } strcpy(argvrestartname, argv[0]); for (cptr = argvrestart, i = 0; i < argc; i++) { strcpy(cptr, argv[i]); *(argvptr++) = cptr; cptr += strlen(argv[i]) + 1; } } #endif /* USING_UTIL_FUNCS_RESTART_MODULE */ if (agent_mode == -1) { if (strstr(argv[0], "agentxd") != NULL) { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, SUB_AGENT); } else { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, MASTER_AGENT); } } else { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, agent_mode); } SOCK_STARTUP; if (init_agent(app_name) != 0) { snmp_log(LOG_ERR, "Agent initialization failed\n"); exit(1); } init_mib_modules(); /* * start library */ init_snmp(app_name); if ((ret = init_master_agent()) != 0) { /* * Some error opening one of the specified agent transports. */ snmp_log(LOG_ERR, "Server Exiting with code 1\n"); exit(1); } /* * Initialize the world. Detach from the shell. Create initial user. */ if(!dont_fork) { int quit = ! netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_QUIT_IMMEDIATELY); ret = netsnmp_daemonize(quit, #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_STDIO snmp_stderrlog_status() #else /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */ 0 #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */ ); /* * xxx-rks: do we care if fork fails? I think we should... */ if(ret != 0) { snmp_log(LOG_ERR, "Server Exiting with code 1\n"); exit(1); } } #if HAVE_GETPID if (pid_file != NULL) { /* * unlink the pid_file, if it exists, prior to open. Without * doing this the open will fail if the user specified pid_file * already exists. */ unlink(pid_file); fd = open(pid_file, O_CREAT | O_EXCL | O_WRONLY, 0600); if (fd == -1) { snmp_log_perror(pid_file); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { exit(1); } } else { if ((PID = fdopen(fd, "w")) == NULL) { snmp_log_perror(pid_file); exit(1); } else { fprintf(PID, "%d\n", (int) getpid()); fclose(PID); } #ifndef _MSC_VER /* The sequence open()/fdopen()/fclose()/close() makes MSVC crash, hence skip the close() call when using the MSVC runtime. */ close(fd); #endif } } #endif #if defined(HAVE_UNISTD_H) && (defined(HAVE_CHOWN) || defined(HAVE_SETGID) || defined(HAVE_SETUID)) { const char *persistent_dir; int uid, gid; persistent_dir = get_persistent_directory(); mkdirhier( persistent_dir, NETSNMP_AGENT_DIRECTORY_MODE, 0 ); uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_USERID); gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_GROUPID); #ifdef HAVE_CHOWN if ( uid != 0 || gid != 0 ) chown( persistent_dir, uid, gid ); #endif #ifdef HAVE_SETGID if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_GROUPID)) > 0) { DEBUGMSGTL(("snmpd/main", "Changing gid to %d.\n", gid)); if (setgid(gid) == -1 #ifdef HAVE_SETGROUPS || setgroups(1, (gid_t *)&gid) == -1 #endif ) { snmp_log_perror("setgid failed"); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { exit(1); } } } #endif #ifdef HAVE_SETUID if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_USERID)) > 0) { #if HAVE_GETPWNAM && HAVE_PWD_H && HAVE_INITGROUPS struct passwd *info; /* * Set supplementary groups before changing UID * (which probably involves giving up privileges) */ info = getpwuid(uid); if (info) { DEBUGMSGTL(("snmpd/main", "Supplementary groups for %s.\n", info->pw_name)); if (initgroups(info->pw_name, (gid != 0 ? (gid_t)gid : info->pw_gid)) == -1) { snmp_log_perror("initgroups failed"); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { exit(1); } } } endpwent(); #endif DEBUGMSGTL(("snmpd/main", "Changing uid to %d.\n", uid)); if (setuid(uid) == -1) { snmp_log_perror("setuid failed"); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { exit(1); } } } #endif } #endif /* * Store persistent data immediately in case we crash later. */ snmp_store(app_name); #ifdef SIGHUP DEBUGMSGTL(("signal", "registering SIGHUP signal handler\n")); signal(SIGHUP, SnmpdReconfig); #endif /* * Send coldstart trap if possible. */ send_easy_trap(0, 0); /* * We're up, log our version number. */ snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version()); #ifdef WIN32SERVICE agent_status = AGENT_RUNNING; #endif netsnmp_addrcache_initialise(); /* * Let systemd know we're up. */ #ifndef NETSNMP_NO_SYSTEMD netsnmp_sd_notify(1, "READY=1\n"); if (prepared_sockets) /* * Clear the environment variable, we already processed all the sockets * by now. */ netsnmp_sd_listen_fds(1); #endif /* * Forever monitor the dest_port for incoming PDUs. */ DEBUGMSGTL(("snmpd/main", "We're up. Starting to process data.\n")); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) receive(); DEBUGMSGTL(("snmpd/main", "sending shutdown trap\n")); SnmpTrapNodeDown(); DEBUGMSGTL(("snmpd/main", "Bye...\n")); snmp_shutdown(app_name); shutdown_master_agent(); shutdown_agent(); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_LEAVE_PIDFILE) && (pid_file != NULL)) { unlink(pid_file); } #ifdef WIN32SERVICE agent_status = AGENT_STOPPED; #endif #ifdef USING_UTIL_FUNCS_RESTART_MODULE SNMP_FREE(argvrestartname); SNMP_FREE(argvrestart); SNMP_FREE(argvrestartp); #endif /* USING_UTIL_FUNCS_RESTART_MODULE */ SOCK_CLEANUP; return 0; } /* End main() -- snmpd */
main(int argc, char *argv[]) #endif { char options[128] = "aAc:CdD::efF:g:hHI:L:m:M:no:O:Ptu:vx:X-:"; netsnmp_session *sess_list = NULL, *ss = NULL; netsnmp_transport *transport = NULL; int arg, i = 0; int uid = 0, gid = 0; int exit_code = 1; char *cp, *listen_ports = NULL; #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) int agentx_subagent = 1; #endif netsnmp_trapd_handler *traph; #ifndef WIN32 int prepared_sockets = 0; #endif #ifndef NETSNMP_NO_SYSTEMD /* check if systemd has sockets for us and don't close them */ prepared_sockets = netsnmp_sd_listen_fds(0); #endif #ifndef WIN32 /* * close all non-standard file descriptors we may have * inherited from the shell. */ if (!prepared_sockets) netsnmp_close_fds(2); #endif #ifdef SIGTERM signal(SIGTERM, term_handler); #endif #ifdef SIGHUP signal(SIGHUP, SIG_IGN); /* do not terminate on early SIGHUP */ #endif #ifdef SIGINT signal(SIGINT, term_handler); #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); /* 'Inline' failure of wayward readers */ #endif /* * register our configuration handlers now so -H properly displays them */ snmptrapd_register_configs( ); #ifdef NETSNMP_USE_MYSQL snmptrapd_register_sql_configs( ); #endif #ifdef NETSNMP_SECMOD_USM init_usm_conf( "snmptrapd" ); #endif /* NETSNMP_SECMOD_USM */ register_config_handler("snmptrapd", "snmpTrapdAddr", parse_trapd_address, free_trapd_address, "string"); register_config_handler("snmptrapd", "doNotLogTraps", parse_config_doNotLogTraps, NULL, "(1|yes|true|0|no|false)"); #if HAVE_GETPID register_config_handler("snmptrapd", "pidFile", parse_config_pidFile, NULL, "string"); #endif #ifdef HAVE_UNISTD_H register_config_handler("snmptrapd", "agentuser", parse_config_agentuser, NULL, "userid"); register_config_handler("snmptrapd", "agentgroup", parse_config_agentgroup, NULL, "groupid"); #endif register_config_handler("snmptrapd", "doNotFork", parse_config_doNotFork, NULL, "(1|yes|true|0|no|false)"); register_config_handler("snmptrapd", "ignoreAuthFailure", parse_config_ignoreAuthFailure, NULL, "(1|yes|true|0|no|false)"); register_config_handler("snmptrapd", "outputOption", parse_config_outputOption, NULL, "string"); /* * Add some options if they are available. */ #if HAVE_GETPID strcat(options, "p:"); #endif #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG #ifdef WIN32 snmp_log_syslogname(app_name_long); #else snmp_log_syslogname(app_name); #endif #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ /* * Now process options normally. */ while ((arg = getopt(argc, argv, options)) != EOF) { switch (arg) { case '-': if (strcasecmp(optarg, "help") == 0 || strcasecmp(optarg, "version") == 0) { version(); exit_code = 0; goto out; } handle_long_opt(optarg); break; case 'a': dropauth = 1; break; case 'A': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPEND_LOGFILES, 1); break; case 'c': if (optarg != NULL) { netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OPTIONALCONFIG, optarg); } else { usage(); goto out; } break; case 'C': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1); break; case 'd': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET, 1); break; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'f': dofork = 0; break; case 'F': if (optarg != NULL) { if (( strncmp( optarg, "print", 5 ) == 0 ) || ( strncmp( optarg, "syslog", 6 ) == 0 ) || ( strncmp( optarg, "execute", 7 ) == 0 )) { /* New style: "type=format" */ trap1_fmt_str_remember = strdup(optarg); cp = strchr( trap1_fmt_str_remember, '=' ); if (cp) *cp = ' '; } else { /* Old style: implicitly "print=format" */ trap1_fmt_str_remember = malloc(strlen(optarg) + 7); sprintf( trap1_fmt_str_remember, "print %s", optarg ); } } else { usage(); goto out; } break; #if HAVE_UNISTD_H case 'g': if (optarg != NULL) { netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_GROUPID, gid = atoi(optarg)); } else { usage(); goto out; } break; #endif case 'h': usage(); exit_code = 0; goto out; case 'H': init_agent("snmptrapd"); #ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE init_notification_log(); #endif #ifdef NETSNMP_EMBEDDED_PERL init_perl(); #endif init_snmp("snmptrapd"); fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage(" "); exit_code = 0; goto out; case 'I': if (optarg != NULL) { add_to_init_list(optarg); } else { usage(); } break; case 'S': fprintf(stderr, "Warning: -S option has been withdrawn; use -Ls <facility> instead\n"); goto out; case 'm': if (optarg != NULL) { setenv("MIBS", optarg, 1); } else { usage(); goto out; } break; case 'M': if (optarg != NULL) { setenv("MIBDIRS", optarg, 1); } else { usage(); goto out; } break; case 'n': netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_NUMERIC_IP, 1); break; case 'o': fprintf(stderr, "Warning: -o option has been withdrawn; use -Lf <file> instead\n"); goto out; case 'O': cp = snmp_out_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown output option passed to -O: %c\n", *cp); usage(); goto out; } break; case 'L': if (snmp_log_options( optarg, argc, argv ) < 0 ) { usage(); goto out; } break; #if HAVE_GETPID case 'p': if (optarg != NULL) { parse_config_pidFile(NULL, optarg); } else { usage(); goto out; } break; #endif case 'P': fprintf(stderr, "Warning: -P option has been withdrawn; use -f -Le instead\n"); goto out; case 's': fprintf(stderr, "Warning: -s option has been withdrawn; use -Lsd instead\n"); goto out; case 't': SyslogTrap++; break; #if HAVE_UNISTD_H case 'u': if (optarg != NULL) { char *ecp; uid = strtoul(optarg, &ecp, 10); #if HAVE_GETPWNAM && HAVE_PWD_H if (*ecp) { struct passwd *info; info = getpwnam(optarg); uid = info ? info->pw_uid : -1; endpwent(); } #endif if (uid < 0) { fprintf(stderr, "Bad user id: %s\n", optarg); goto out; } netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_USERID, uid); } else { usage(); goto out; } break; #endif case 'v': version(); exit(0); break; #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) case 'x': if (optarg != NULL) { netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET, optarg); } else { usage(); goto out; } break; case 'X': agentx_subagent = 0; break; #endif default: fprintf(stderr, "invalid option: -%c\n", arg); usage(); goto out; break; } } if (optind < argc) { /* * There are optional transport addresses on the command line. */ for (i = optind; i < argc; i++) { char *astring; if (listen_ports != NULL) { astring = malloc(strlen(listen_ports) + 2 + strlen(argv[i])); if (astring == NULL) { fprintf(stderr, "malloc failure processing argv[%d]\n", i); goto out; } sprintf(astring, "%s,%s", listen_ports, argv[i]); free(listen_ports); listen_ports = astring; } else { listen_ports = strdup(argv[i]); if (listen_ports == NULL) { fprintf(stderr, "malloc failure processing argv[%d]\n", i); goto out; } } } } SOCK_STARTUP; /* * I'm being lazy here, and not checking the * return value from these registration calls. * Don't try this at home, children! */ if (0 == snmp_get_do_logging()) { #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, syslog_handler); traph->authtypes = TRAP_AUTH_LOG; snmp_enable_syslog(); #else /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_STDIO traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, print_handler); traph->authtypes = TRAP_AUTH_LOG; snmp_enable_stderr(); #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */ #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ } else { traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, print_handler); traph->authtypes = TRAP_AUTH_LOG; } #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) /* * we're an agentx subagent? */ if (agentx_subagent) { /* * make us a agentx client. */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1); } #endif /* * don't fail if we can't do agentx (ie, socket not there, or not root) */ netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS); /* * ignore any warning messages. */ netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS); /* * initialize the agent library */ init_agent("snmptrapd"); #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) #ifdef NETSNMP_FEATURE_CHECKING netsnmp_feature_require(register_snmpEngine_scalars_context) #endif /* NETSNMP_FEATURE_CHECKING */ /* * initialize local modules */ if (agentx_subagent) { #ifdef USING_SNMPV3_SNMPENGINE_MODULE extern void register_snmpEngine_scalars_context(const char *); #endif subagent_init(); #ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE /* register the notification log table */ if (should_init("notificationLogMib")) { netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_NOTIF_LOG_CTX, "snmptrapd"); traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_POST_HANDLER, notification_handler); traph->authtypes = TRAP_AUTH_LOG; init_notification_log(); } #endif #ifdef USING_SNMPV3_SNMPENGINE_MODULE /* * register scalars from SNMP-FRAMEWORK-MIB::snmpEngineID group; * allows engineID probes via the master agent under the * snmptrapd context */ register_snmpEngine_scalars_context("snmptrapd"); #endif } #endif /* USING_AGENTX_SUBAGENT_MODULE && !NETSNMP_SNMPTRAPD_DISABLE_AGENTX */ /* register our authorization handler */ init_netsnmp_trapd_auth(); #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) if (agentx_subagent) { #ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE extern void init_register_nsVacm_context(const char *); #endif #ifdef USING_SNMPV3_USMUSER_MODULE #ifdef NETSNMP_FEATURE_CHECKING netsnmp_feature_require(init_register_usmUser_context) #endif /* NETSNMP_FEATURE_CHECKING */ extern void init_register_usmUser_context(const char *); /* register ourselves as having a USM user database */ init_register_usmUser_context("snmptrapd"); #endif #ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE /* register net-snmp vacm extensions */ init_register_nsVacm_context("snmptrapd"); #endif #ifdef USING_TLSTM_MIB_SNMPTLSTMCERTTOTSNTABLE_MODULE init_snmpTlstmCertToTSNTable_context("snmptrapd"); #endif } #endif #ifdef NETSNMP_EMBEDDED_PERL init_perl(); { /* set the default path to load */ char init_file[SNMP_MAXBUF]; snprintf(init_file, sizeof(init_file) - 1, "%s/%s", SNMPSHAREPATH, "snmp_perl_trapd.pl"); netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_PERL_INIT_FILE, init_file); } #endif /* * Initialize the world. */ init_snmp("snmptrapd"); #ifdef SIGHUP signal(SIGHUP, hup_handler); #endif if (trap1_fmt_str_remember) { parse_format( NULL, trap1_fmt_str_remember ); } if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) { /* * just starting up to process specific configuration and then * shutting down immediately. */ netsnmp_running = 0; } /* * if no logging options on command line or in conf files, use syslog */ if (0 == snmp_get_do_logging()) { #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG #ifdef WIN32 snmp_enable_syslog_ident(app_name_long, Facility); #else snmp_enable_syslog_ident(app_name, Facility); #endif #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ } if (listen_ports) cp = listen_ports; else cp = default_port; while (cp != NULL) { char *sep = strchr(cp, ','); if (sep != NULL) { *sep = 0; } transport = netsnmp_transport_open_server("snmptrap", cp); if (transport == NULL) { snmp_log(LOG_ERR, "couldn't open %s -- errno %d (\"%s\")\n", cp, errno, strerror(errno)); snmptrapd_close_sessions(sess_list); goto sock_cleanup; } else { ss = snmptrapd_add_session(transport); if (ss == NULL) { /* * Shouldn't happen? We have already opened the transport * successfully so what could have gone wrong? */ snmptrapd_close_sessions(sess_list); snmp_log(LOG_ERR, "couldn't open snmp - %s", strerror(errno)); goto sock_cleanup; } else { ss->next = sess_list; sess_list = ss; } } /* * Process next listen address, if there is one. */ if (sep != NULL) { *sep = ','; cp = sep + 1; } else { cp = NULL; } } SNMP_FREE(listen_ports); /* done with them */ #ifdef NETSNMP_USE_MYSQL if( netsnmp_mysql_init() ) { fprintf(stderr, "MySQL initialization failed\n"); goto sock_cleanup; } #endif #ifndef WIN32 /* * fork the process to the background if we are not printing to stderr */ if (dofork && netsnmp_running) { int fd; #if HAVE_FORKALL switch (forkall()) { #else switch (fork()) { #endif case -1: fprintf(stderr, "bad fork - %s\n", strerror(errno)); goto sock_cleanup; case 0: /* * become process group leader */ if (setsid() == -1) { fprintf(stderr, "bad setsid - %s\n", strerror(errno)); goto sock_cleanup; } /* * if we are forked, we don't want to print out to stdout or stderr */ fd = open("/dev/null", O_RDWR); if (fd >= 0) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); close(fd); } break; default: _exit(0); } } #endif /* WIN32 */ #if HAVE_GETPID if (pid_file != NULL) { if ((PID = fopen(pid_file, "w")) == NULL) { snmp_log_perror("fopen"); goto sock_cleanup; } fprintf(PID, "%d\n", (int) getpid()); fclose(PID); free_config_pidFile(); } #endif snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version()); /* * ignore early sighup during startup */ reconfig = 0; #if HAVE_UNISTD_H #ifdef HAVE_SETGID if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_GROUPID)) > 0) { DEBUGMSGTL(("snmptrapd/main", "Changing gid to %d.\n", gid)); if (setgid(gid) == -1 #ifdef HAVE_SETGROUPS || setgroups(1, (gid_t *)&gid) == -1 #endif ) { snmp_log_perror("setgid failed"); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { goto sock_cleanup; } } } #endif #ifdef HAVE_SETUID if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_USERID)) != 0) { DEBUGMSGTL(("snmptrapd/main", "Changing uid to %d.\n", uid)); if (setuid(uid) == -1) { snmp_log_perror("setuid failed"); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { goto sock_cleanup; } } } #endif #endif /* * Let systemd know we're up. */ #ifndef NETSNMP_NO_SYSTEMD netsnmp_sd_notify(1, "READY=1\n"); if (prepared_sockets) /* * Clear the environment variable, we already processed all the sockets * by now. */ netsnmp_sd_listen_fds(1); #endif #ifdef WIN32SERVICE trapd_status = SNMPTRAPD_RUNNING; #endif snmptrapd_main_loop(); if (snmp_get_do_logging()) { struct tm *tm; time_t timer; time(&timer); tm = localtime(&timer); snmp_log(LOG_INFO, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Stopped.\n", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, netsnmp_get_version()); } snmp_log(LOG_INFO, "Stopping snmptrapd\n"); #ifdef NETSNMP_EMBEDDED_PERL shutdown_perl(); #endif snmptrapd_close_sessions(sess_list); snmp_shutdown("snmptrapd"); #ifdef WIN32SERVICE trapd_status = SNMPTRAPD_STOPPED; #endif snmp_disable_log(); exit_code = 0; sock_cleanup: SOCK_CLEANUP; out: return exit_code; } /* * Read the configuration files. Implemented as a signal handler so that * receipt of SIGHUP will cause configuration to be re-read when the * trap daemon is running detatched from the console. * */ void trapd_update_config(void) { free_config(); #ifdef USING_MIBII_VACM_CONF_MODULE vacm_standard_views(0,0,NULL,NULL); #endif read_configs(); }
netsnmp_variable_list * register_index(netsnmp_variable_list * varbind, int flags, netsnmp_session * ss) { netsnmp_variable_list *rv = NULL; struct snmp_index *new_index, *idxptr, *idxptr2; struct snmp_index *prev_oid_ptr, *prev_idx_ptr; int res, res2, i; DEBUGMSGTL(("register_index", "register ")); DEBUGMSGVAR(("register_index", varbind)); DEBUGMSG(("register_index", "for session %8p\n", ss)); #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING) if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) { return (agentx_register_index(ss, varbind, flags)); } #endif /* * Look for the requested OID entry */ prev_oid_ptr = NULL; prev_idx_ptr = NULL; res = 1; res2 = 1; for (idxptr = snmp_index_head; idxptr != NULL; prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) { if ((res = snmp_oid_compare(varbind->name, varbind->name_length, idxptr->varbind->name, idxptr->varbind->name_length)) <= 0) break; } /* * Found the OID - now look at the registered indices */ if (res == 0 && idxptr) { if (varbind->type != idxptr->varbind->type) return NULL; /* wrong type */ /* * If we've been asked for an arbitrary new value, * then find the end of the list. * If we've been asked for any arbitrary value, * then look for an unused entry, and use that. * If there aren't any, continue as for new. * Otherwise, locate the given value in the (sorted) * list of already allocated values */ if (flags & ALLOCATE_ANY_INDEX) { for (idxptr2 = idxptr; idxptr2 != NULL; prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) { if ((rv = snmp_clone_varbind(idxptr2->varbind)) != NULL) { idxptr2->session = ss; idxptr2->allocated = 1; } return rv; } } } else { for (idxptr2 = idxptr; idxptr2 != NULL; prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { switch (varbind->type) { case ASN_INTEGER: res2 = (*varbind->val.integer - *idxptr2->varbind->val.integer); break; case ASN_OCTET_STR: i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len); res2 = memcmp(varbind->val.string, idxptr2->varbind->val.string, i); break; case ASN_OBJECT_ID: res2 = snmp_oid_compare(varbind->val.objid, varbind->val_len / sizeof(oid), idxptr2->varbind->val.objid, idxptr2->varbind->val_len / sizeof(oid)); break; default: return NULL; /* wrong type */ } if (res2 <= 0) break; } if (res2 == 0) { if (idxptr2->allocated) { /* * No good: the index is in use. */ return NULL; } else { /* * Okay, it's unallocated, we can just claim ownership * here. */ if ((rv = snmp_clone_varbind(idxptr2->varbind)) != NULL) { idxptr2->session = ss; idxptr2->allocated = 1; } return rv; } } } } /* * OK - we've now located where the new entry needs to * be fitted into the index registry tree * To recap: * 'prev_oid_ptr' points to the head of the OID index * list prior to this one. If this is null, then * it means that this is the first OID in the list. * 'idxptr' points either to the head of this OID list, * or the next OID (if this is a new OID request) * These can be distinguished by the value of 'res'. * * 'prev_idx_ptr' points to the index entry that sorts * immediately prior to the requested value (if any). * If an arbitrary value is required, then this will * point to the last allocated index. * If this pointer is null, then either this is a new * OID request, or the requested value is the first * in the list. * 'idxptr2' points to the next sorted index (if any) * but is not actually needed any more. * * Clear? Good! * I hope you've been paying attention. * There'll be a test later :-) */ /* * We proceed by creating the new entry * (by copying the entry provided) */ new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index)); if (new_index == NULL) return NULL; if (NULL == snmp_varlist_add_variable(&new_index->varbind, varbind->name, varbind->name_length, varbind->type, varbind->val.string, varbind->val_len)) { /* * if (snmp_clone_var( varbind, new_index->varbind ) != 0 ) */ free(new_index); return NULL; } new_index->session = ss; new_index->allocated = 1; if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX) new_index->varbind->val.string[new_index->varbind->val_len] = 0; /* * If we've been given a value, then we can use that, but * otherwise, we need to create a new value for this entry. * Note that ANY_INDEX and NEW_INDEX are both covered by this * test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?) */ if (flags & ALLOCATE_ANY_INDEX) { if (prev_idx_ptr) { if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind) != 0) { free(new_index); return NULL; } } else new_index->varbind->val.string = new_index->varbind->buf; switch (varbind->type) { case ASN_INTEGER: if (prev_idx_ptr) { (*new_index->varbind->val.integer)++; } else *(new_index->varbind->val.integer) = 1; new_index->varbind->val_len = sizeof(long); break; case ASN_OCTET_STR: if (prev_idx_ptr) { i = new_index->varbind->val_len - 1; while (new_index->varbind->buf[i] == 'z') { new_index->varbind->buf[i] = 'a'; i--; if (i < 0) { i = new_index->varbind->val_len; new_index->varbind->buf[i] = 'a'; new_index->varbind->buf[i + 1] = 0; } } new_index->varbind->buf[i]++; } else strcpy((char *) new_index->varbind->buf, "aaaa"); new_index->varbind->val_len = strlen((char *) new_index->varbind->buf); break; case ASN_OBJECT_ID: if (prev_idx_ptr) { i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1; while (new_index->varbind->val.objid[i] == 255) { new_index->varbind->val.objid[i] = 1; i--; if (i == 0 && new_index->varbind->val.objid[0] == 2) { new_index->varbind->val.objid[0] = 1; i = new_index->varbind->val_len / sizeof(oid); new_index->varbind->val.objid[i] = 0; new_index->varbind->val_len += sizeof(oid); } } new_index->varbind->val.objid[i]++; } else { /* * If the requested OID name is small enough, * * append another OID (1) and use this as the * * default starting value for new indexes. */ if ((varbind->name_length + 1) * sizeof(oid) <= 40) { for (i = 0; i < (int) varbind->name_length; i++) new_index->varbind->val.objid[i] = varbind->name[i]; new_index->varbind->val.objid[varbind->name_length] = 1; new_index->varbind->val_len = (varbind->name_length + 1) * sizeof(oid); } else { /* * Otherwise use '.1.1.1.1...' */ i = 40 / sizeof(oid); if (i > 4) i = 4; new_index->varbind->val_len = i * (sizeof(oid)); for (i--; i >= 0; i--) new_index->varbind->val.objid[i] = 1; } } break; default: snmp_free_var(new_index->varbind); free(new_index); return NULL; /* Index type not supported */ } } /* * Try to duplicate the new varbind for return. */ if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) { snmp_free_var(new_index->varbind); free(new_index); return NULL; } /* * Right - we've set up the new entry. * All that remains is to link it into the tree. * There are a number of possible cases here, * so watch carefully. */ if (prev_idx_ptr) { new_index->next_idx = prev_idx_ptr->next_idx; new_index->next_oid = prev_idx_ptr->next_oid; prev_idx_ptr->next_idx = new_index; } else { if (res == 0 && idxptr) { new_index->next_idx = idxptr; new_index->next_oid = idxptr->next_oid; } else { new_index->next_idx = NULL; new_index->next_oid = idxptr; } if (prev_oid_ptr) { while (prev_oid_ptr) { prev_oid_ptr->next_oid = new_index; prev_oid_ptr = prev_oid_ptr->next_idx; } } else snmp_index_head = new_index; } return rv; }