void init_master(void) { struct snmp_session sess, *session; if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != MASTER_AGENT ) return; DEBUGMSGTL(("agentx/master","initializing...\n")); snmp_sess_init( &sess ); sess.version = AGENTX_VERSION_1; sess.flags |= SNMP_FLAGS_STREAM_SOCKET; if ( ds_get_string(DS_APPLICATION_ID, DS_AGENT_X_SOCKET) ) sess.peername = strdup(ds_get_string(DS_APPLICATION_ID, DS_AGENT_X_SOCKET)); else sess.peername = strdup(AGENTX_SOCKET); if ( sess.peername[0] == '/' ) { /* * If this is a Unix pathname, * try and create the directory first. */ if (mkdirhier(sess.peername, AGENT_DIRECTORY_MODE, 1)) { snmp_log(LOG_ERR, "Failed to create the directory for the agentX socket: %s\n", sess.peername); } } /* * Otherwise, let 'snmp_open' interpret the string. */ sess.local_port = AGENTX_PORT; /* Indicate server & set default port */ sess.remote_port = 0; sess.callback = handle_master_agentx_packet; session = snmp_open_ex( &sess, 0, agentx_parse, 0, agentx_build, agentx_check_packet ); if ( session == NULL && sess.s_errno == EADDRINUSE ) { /* * Could be a left-over socket (now deleted) * Try again */ session = snmp_open_ex( &sess, 0, agentx_parse, 0, agentx_build, agentx_check_packet ); } if ( session == NULL ) { /* diagnose snmp_open errors with the input struct snmp_session pointer */ snmp_sess_perror("init_master", &sess); if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) exit(1); } DEBUGMSGTL(("agentx/master","initializing... DONE\n")); }
/*******************************************************************-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 init_master_agent(int dest_port, int (*pre_parse) (struct snmp_session *, snmp_ipaddr), int (*post_parse) (struct snmp_session *, struct snmp_pdu *,int)) { struct snmp_session sess, *session; if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != MASTER_AGENT ) return 0; /* no error if ! MASTER_AGENT */ DEBUGMSGTL(("snmpd","installing master agent on port %d\n", dest_port)); snmp_sess_init( &sess ); sess.version = SNMP_DEFAULT_VERSION; sess.peername = SNMP_DEFAULT_PEERNAME; sess.community_len = SNMP_DEFAULT_COMMUNITY_LEN; sess.local_port = dest_port; sess.callback = handle_snmp_packet; sess.authenticator = NULL; sess.flags = ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS); session = snmp_open_ex( &sess, pre_parse, 0, post_parse, 0, 0 ); if ( session == NULL ) { /* diagnose snmp_open errors with the input struct snmp_session pointer */ snmp_sess_perror("init_master_agent", &sess); return 1; } main_session = session; return 0; }
void snmp_log_string (int priority, const char *string) { char sbuf[40]; struct snmp_log_message slm; #if HAVE_SYSLOG_H if (do_syslogging) { syslog(priority, string); } #endif if (do_log_callback) { slm.priority = priority; slm.msg = string; snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, &slm); } if (do_filelogging || do_stderrlogging) { if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_LOG_TIMESTAMP) && newline) { sprintf_stamp(NULL, (char *)&sbuf); } else { strcpy(sbuf, ""); } newline = string[strlen(string)-1] == '\n'; if (do_filelogging) fprintf(logfile, "%s%s", sbuf, string); if (do_stderrlogging) fprintf(stderr, "%s%s", sbuf, string); } }
void init_agent_read_config (const char *app) { if ( app != NULL ) ds_set_string(DS_LIBRARY_ID, DS_LIB_APPTYPE, app); register_app_config_handler("authtrapenable", snmpd_parse_config_authtrap, NULL, "1 | 2\t\t(1 = enable, 2 = disable)"); if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == MASTER_AGENT ) { register_app_config_handler("trapsink", snmpd_parse_config_trapsink, snmpd_free_trapsinks, "host [community]"); register_app_config_handler("trap2sink", snmpd_parse_config_trap2sink, NULL, "host [community]"); register_app_config_handler("informsink", snmpd_parse_config_informsink, NULL, "host [community]"); } register_app_config_handler("trapcommunity", snmpd_parse_config_trapcommunity, snmpd_free_trapcommunity, "community-string"); #include "mib_module_dot_conf.h" #ifdef TESTING print_config_handlers(); #endif }
void setup_tree (void) { #ifdef USING_AGENTX_SUBAGENT_MODULE int role; role = ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE); ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, MASTER_AGENT); #endif register_mib("", NULL, 0, 0, root_subtrees[0].name, root_subtrees[0].namelen); register_mib("", NULL, 0, 0, root_subtrees[1].name, root_subtrees[1].namelen); register_mib("", NULL, 0, 0, root_subtrees[2].name, root_subtrees[2].namelen); /* Support for 'static' subtrees (subtrees_old) has now been dropped */ /* No longer necessary to sort the mib tree - this is inherent in the construction of the subtree structure */ #ifdef USING_AGENTX_SUBAGENT_MODULE ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, role); #endif }
void init_agent (const char *app) { /* 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 */ ds_set_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG, 1); #ifdef CYGPKG_SNMPAGENT_V3_SUPPORT usm_set_reportErrorOnUnknownID(1); #endif #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 /* initialize agentx subagent if necessary. */ #ifdef USING_AGENTX_SUBAGENT_MODULE if(ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT) subagent_pre_init(); #endif } /* end init_agent() */
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 && !ds_get_boolean(DS_APPLICATION_ID, 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 && !ds_get_boolean(DS_APPLICATION_ID, 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 read_premib_configs (void) { DEBUGMSGTL(("read_config","reading premib configuration tokens\n")); if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS)) read_config_files(PREMIB_CONFIG); snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_PREMIB_READ_CONFIG, NULL); }
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? */ }
void init_kmem(const char *file) { kmem = open(file, O_RDONLY); if (kmem < 0 && !ds_get_boolean(DS_APPLICATION_ID, 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 && !ds_get_boolean(DS_APPLICATION_ID, 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 && !ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)){ snmp_log_perror(DMEM_LOC); exit(1); } fcntl(swap,F_SETFD,1); #endif }
void read_configs (void) { char *optional_config = ds_get_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG); char *type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE); DEBUGMSGTL(("read_config","reading normal configuration tokens\n")); if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS)) read_config_files(NORMAL_CONFIG); /* do this even when the normal above wasn't done */ if (optional_config && type) read_config_with_type(optional_config, type); snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, NULL); }
void set_an_alarm(void) { int nexttime = get_next_alarm_delay_time(); /* we don't use signals if they asked us nicely not to. It's expected they'll check the next alarm time and do their own calling of run_alarms(). */ if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG) && nexttime) { #ifndef WIN32 #ifdef SIGALRM //FIXMEHMTHMT alarm(nexttime); DEBUGMSGTL(("snmp_alarm_set_an_alarm","setting an alarm for %d seconds from now\n",nexttime)); signal(SIGALRM, alarm_handler); #endif /* SIGALRM */ #endif } else { DEBUGMSGTL(("snmp_alarm_set_an_alarm","no alarms found to handle\n")); } }
void init_sysORTable(void) { /* register ourselves with the agent to handle our mib tree */ #ifdef USING_AGENTX_SUBAGENT_MODULE if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == MASTER_AGENT ) (void)register_mib_priority("mibII/sysORTable", (struct variable *) sysORTable_variables, sizeof(struct variable2), sizeof(sysORTable_variables)/sizeof(struct variable2), sysORTable_variables_oid, sizeof(sysORTable_variables_oid)/sizeof(oid), 1); else #endif REGISTER_MIB("mibII/sysORTable", sysORTable_variables, variable2, sysORTable_variables_oid); #ifdef USING_MIBII_SYSTEM_MIB_MODULE if ( ++system_module_count == 3 ) REGISTER_SYSOR_TABLE( system_module_oid, system_module_oid_len, "The MIB module for SNMPv2 entities"); #endif gettimeofday(&sysOR_lastchange, NULL); }
struct variable_list* register_index(struct variable_list *varbind, int flags, struct snmp_session *ss ) { struct snmp_index *new_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 (ds_get_boolean(DS_APPLICATION_ID, 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->session == NULL ) { idxptr2->session = ss ; return &idxptr2->varbind; } } } 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 ) return NULL; /* duplicate value */ } } /* * 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 *)malloc( sizeof( struct snmp_index )); if (new_index == NULL) return NULL; if (snmp_clone_var( varbind, &new_index->varbind ) != 0 ) { free( new_index ); return NULL; } new_index->session = ss; 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: free( new_index ); return NULL; /* Index type not supported */ } } /* * 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 &new_index->varbind; }
/*******************************************************************-o-****** * read_config * * Parameters: * *filename * *line_handler * when * * Read <filename> and process each line in accordance with the list of * <line_handler> functions. * * * For each line in <filename>, search the list of <line_handler>'s * for an entry that matches the first token on the line. This comparison is * case insensitive. * * For each match, check that <when> is the designated time for the * <line_handler> function to be executed before processing the line. */ void read_config(const char *filename, struct config_line *line_handler, int when) { #ifdef CYGPKG_SNMPLIB_FILESYSTEM_SUPPORT FILE *ifile; char line[STRINGMAX], token[STRINGMAX], tmpbuf[STRINGMAX]; char *cptr; int i, done; struct config_line *lptr; linecount = 0; curfilename = filename; if ((ifile = fopen(filename, "r")) == NULL) { #ifdef ENOENT if (errno == ENOENT) { DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno))); } else #endif /* ENOENT */ #ifdef EACCES if (errno == EACCES) { DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno))); } else #endif /* EACCES */ #if defined(ENOENT) || defined(EACCES) { snmp_log_perror(filename); } #else /* defined(ENOENT) || defined(EACCES) */ snmp_log_perror(filename); #endif /* ENOENT */ return; } else { DEBUGMSGTL(("read_config", "Reading configuration %s\n", filename)); } while (fgets(line, sizeof(line), ifile) != NULL) { lptr = line_handler; linecount++; cptr = line; i = strlen(line)-1; if (line[i] == '\n') line[i] = 0; /* check blank line or # comment */ if ((cptr = skip_white(cptr))) { cptr = copy_word(cptr,token); if (cptr == NULL) { sprintf(tmpbuf,"Blank line following %s token.", token); config_perror(tmpbuf); } else { for(lptr = line_handler, done=0; lptr != NULL && !done; lptr = lptr->next) { if (!strcasecmp(token,lptr->config_token)) { if (when == EITHER_CONFIG || lptr->config_time == when) { DEBUGMSGTL(("read_config", "%s:%d Parsing: %s\n", filename, linecount, line)); (*(lptr->parse_line))(token,cptr); } done = 1; } } if (!done && when != PREMIB_CONFIG && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_NO_TOKEN_WARNINGS)) { sprintf(tmpbuf,"Unknown token: %s.", token); config_pwarn(tmpbuf); } } } } fclose(ifile); #endif return; } /* end read_config() */
int unregister_index(struct variable_list *varbind, int remember, struct snmp_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 (ds_get_boolean(DS_APPLICATION_ID, 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) { i = SNMP_MIN(varbind->val_len, idxptr2->varbind.val_len); res2 = memcmp(varbind->val.string, idxptr2->varbind.val.string, i); if ( res2 <= 0 ) break; } if ( res2 != 0 ) 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->session = NULL; /* Unused index */ 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( (struct variable_list *)idxptr2 ); return SNMP_ERR_NOERROR; }
int main(int argc, char *argv[]) { int arg; char *current_name = NULL, *cp = NULL; oid name[MAX_OID_LEN]; size_t name_length; int description = 0; int print = 0; int find_all = 0; int width = 1000000; /* * usage: snmptranslate name */ while ((arg = getopt(argc, argv, "Vhm:M:w:D:P:T:O:I:")) != EOF) { switch (arg) { case 'h': usage(); exit(1); case 'm': setenv("MIBS", optarg, 1); break; case 'M': setenv("MIBDIRS", optarg, 1); break; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'V': fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); exit(0); break; case 'P': cp = snmp_mib_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown parser option to -P: %c.\n", *cp); usage(); exit(1); } break; case 'O': cp = snmp_out_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown OID option to -O: %c.\n", *cp); usage(); exit(1); } break; case 'I': cp = snmp_in_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown OID option to -I: %c.\n", *cp); usage(); exit(1); } break; case 'T': for (cp = optarg; *cp; cp++) { switch (*cp) { case 'l': print = 3; #ifdef __vms print_oid_report_en_labeledoid(); #else print_oid_report_enable_labeledoid(); #endif break; case 'o': print = 3; print_oid_report_enable_oid(); break; case 's': print = 3; #ifdef __vms print_oid_report_en_symbolic(); #else print_oid_report_enable_symbolic(); #endif break; case 't': print = 3; print_oid_report_enable_suffix(); break; case 'd': description = 1; snmp_set_save_descriptions(1); break; case 'B': find_all = 1; break; case 'p': print = 1; break; case 'a': print = 2; break; default: fprintf(stderr, "Invalid -T<lostpad> character: %c\n", *cp); usage(); exit(1); break; } } break; default: fprintf(stderr, "invalid option: -%c\n", arg); usage(); exit(1); break; } } init_snmp("snmpapp"); if (optind < argc) current_name = argv[optind]; if (current_name == NULL) { switch (print) { default: usage(); exit(1); case 1: print_mib_tree(stdout, get_tree_head(), width); break; case 2: print_ascii_dump(stdout); break; case 3: print_oid_report(stdout); break; } exit(0); } do { name_length = MAX_OID_LEN; if (snmp_get_random_access()) { if (!get_node(current_name, name, &name_length)) { fprintf(stderr, "Unknown object identifier: %s\n", current_name); exit(2); } } else if (find_all) { if (0 == show_all_matched_objects(stdout, current_name, name, &name_length, description, width)) { fprintf(stderr, "Unable to find a matching object identifier for \"%s\"\n", current_name); exit(1); } exit(0); } else if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_REGEX_ACCESS)) { if (0 == get_wild_node(current_name, name, &name_length)) { fprintf(stderr, "Unable to find a matching object identifier for \"%s\"\n", current_name); exit(1); } } else { if (!read_objid(current_name, name, &name_length)) { snmp_perror(current_name); exit(2); } } if (print == 1) { struct tree *tp; tp = get_tree(name, name_length, get_tree_head()); print_mib_tree(stdout, tp, width); } else { print_objid(name, name_length); if (description) { print_description(name, name_length, width); } } current_name = argv[++optind]; if (current_name != NULL) printf("\n"); } while (optind < argc); return (0); }
int main(int argc, char *argv[]) { int arg, i; int ret; u_short dest_port = SNMP_PORT; int dont_fork = 0; char logfile[SNMP_MAXBUF_SMALL]; char *cptr, **argvptr; char *pid_file = NULL; #if HAVE_GETPID FILE *PID; #endif int dont_zero_log = 0; int stderr_log=0, syslog_log=0; int uid=0, gid=0; logfile[0] = 0; #ifdef LOGFILE strcpy(logfile, LOGFILE); #endif /* * usage: snmpd */ for (arg = 1; arg < argc; arg++) { if (argv[arg][0] == '-') { switch (argv[arg][1]) { case 'c': if (++arg == argc) usage(argv[0]); ds_set_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG, argv[arg]); break; case 'C': ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS, 1); break; case 'd': snmp_set_dump_packet(++snmp_dump_packet); ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1); break; case 'q': snmp_set_quick_print(1); break; case 'T': if (argv[arg][2] != '\0') cptr = &argv[arg][2]; else if (++arg>argc) { fprintf(stderr,"Need UDP or TCP after -T flag.\n"); usage(argv[0]); exit(1); } else { cptr = argv[arg]; } if (strcasecmp(cptr,"TCP") == 0) { ds_set_int(DS_APPLICATION_ID, DS_AGENT_FLAGS, ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS) | SNMP_FLAGS_STREAM_SOCKET); } else if (strcasecmp(cptr,"UDP") == 0) { /* default, do nothing */ } else { fprintf(stderr, "Unknown transport \"%s\" after -T flag.\n", cptr); usage(argv[0]); exit(1); } break; case 'D': debug_register_tokens(&argv[arg][2]); snmp_set_do_debugging(1); break; case 'p': if (++arg == argc) usage(argv[0]); dest_port = atoi(argv[arg]); if (dest_port <= 0) usage(argv[0]); break; case 'x': if (++arg == argc) usage(argv[0]); ds_set_string(DS_APPLICATION_ID, DS_AGENT_X_SOCKET, argv[arg]); break; case 'r': ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS, 1); break; case 'P': if (++arg == argc) usage(argv[0]); pid_file = argv[arg]; case 'a': log_addresses++; break; case 'V': ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1); break; case 'f': dont_fork = 1; break; case 'l': if (++arg == argc) usage(argv[0]); strcpy(logfile, argv[arg]); break; case 'L': stderr_log=1; break; case 's': syslog_log=1; break; 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: [email protected]\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: [email protected]\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 */
int handle_var_list(struct agent_snmp_session *asp) { struct variable_list *varbind_ptr; u_char statType; u_char *statP; size_t statLen; u_short acl; WriteMethod *write_method; AddVarMethod *add_method; int noSuchObject = TRUE; int count, view; count = 0; varbind_ptr = asp->start; if ( !varbind_ptr ) { return SNMP_ERR_NOERROR; } while (1) { count++; statp_loop: statP = getStatPtr( varbind_ptr->name, &varbind_ptr->name_length, &statType, &statLen, &acl, asp->exact, &write_method, asp->pdu, &noSuchObject); if (statP == NULL && (asp->rw != WRITE || write_method == NULL)) { /* Careful -- if the varbind was lengthy, it will have allocated some memory. */ snmp_set_var_value(varbind_ptr, NULL, 0); varbind_ptr->val.integer = NULL; varbind_ptr->val_len = 0; if ( asp->exact ) { if ( noSuchObject == TRUE ){ statType = SNMP_NOSUCHOBJECT; } else { statType = SNMP_NOSUCHINSTANCE; } } else { statType = SNMP_ENDOFMIBVIEW; } if (asp->pdu->version == SNMP_VERSION_1) { asp->pdu->errstat = SNMP_ERR_NOSUCHNAME; asp->pdu->errindex = count; return SNMP_ERR_NOSUCHNAME; } else if (asp->rw == WRITE) { asp->pdu->errstat = ( noSuchObject ? SNMP_ERR_NOTWRITABLE : SNMP_ERR_NOCREATION ); asp->pdu->errindex = count; return asp->pdu->errstat; } else varbind_ptr->type = statType; } /* Delegated variables should be added to the relevant outgoing request */ else if ( IS_DELEGATED(statType)) { add_method = (AddVarMethod*)statP; statType = (*add_method)( asp, varbind_ptr ); } /* GETNEXT/GETBULK should just skip inaccessible entries */ else if ((view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length, asp->pdu, varbind_ptr->type)) && !asp->exact) { if (view != 5) send_easy_trap(SNMP_TRAP_AUTHFAIL, 0); goto statp_loop; } /* Other access problems are permanent */ else if (( asp->rw == WRITE && !(acl & 2)) || view) { if (asp->pdu->version == SNMP_VERSION_1 || asp->rw != WRITE) { if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)) DEBUGMSGTL(("snmp_agent", " >> noSuchName (read-only)\n")); ERROR_MSG("read-only"); statType = SNMP_ERR_NOSUCHNAME; } else { if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)) DEBUGMSGTL(("snmp_agent", " >> notWritable\n")); ERROR_MSG("Not Writable"); statType = SNMP_ERR_NOTWRITABLE; } asp->pdu->errstat = statType; asp->pdu->errindex = count; send_easy_trap(SNMP_TRAP_AUTHFAIL, 0); return statType; } else { /* dump verbose info */ if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) && statP) dump_var(varbind_ptr->name, varbind_ptr->name_length, statType, statP, statLen); /* FINALLY we can act on SET requests ....*/ if ( asp->rw == WRITE ) { if ( write_method != NULL ) { statType = (*write_method)(asp->mode, varbind_ptr->val.string, varbind_ptr->type, varbind_ptr->val_len, statP, varbind_ptr->name, varbind_ptr->name_length); if (statType != SNMP_ERR_NOERROR) { asp->pdu->errstat = statType; asp->pdu->errindex = count; return statType; } } else { if (!goodValue(varbind_ptr->type, varbind_ptr->val_len, statType, statLen)){ if (asp->pdu->version == SNMP_VERSION_1) statType = SNMP_ERR_BADVALUE; else statType = SNMP_ERR_WRONGTYPE; /* poor approximation */ asp->pdu->errstat = statType; asp->pdu->errindex = count; return statType; } /* actually do the set if necessary */ if (asp->mode == COMMIT) setVariable(varbind_ptr->val.string, varbind_ptr->type, varbind_ptr->val_len, statP, statLen); } } /* ... or save the results from assorted GETs */ else { snmp_set_var_value(varbind_ptr, statP, statLen); varbind_ptr->type = statType; } } if ( varbind_ptr == asp->end ) return SNMP_ERR_NOERROR; varbind_ptr = varbind_ptr->next_variable; if ( asp->mode == RESERVE1 ) snmp_vars_inc++; } }
int main(int argc, char *argv[]) { netsnmp_session session, *ss; netsnmp_pdu *pdu; netsnmp_pdu *response; netsnmp_variable_list *vars; int arg; int count; int current_name = 0; char *names[128]; oid name[MAX_OID_LEN]; size_t name_length; int status; int exitval = 0; /* * get the common command line arguments */ switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) { case -2: exit(0); case -1: usage(); exit(1); default: break; } if (arg >= argc) { fprintf(stderr, "Missing object name\n"); usage(); exit(1); } /* * get the object names */ for (; arg < argc; arg++) names[current_name++] = argv[arg]; SOCK_STARTUP; /* * Open an SNMP session. */ ss = snmp_open(&session); if (ss == NULL) { /* * diagnose snmp_open errors with the input netsnmp_session pointer */ snmp_sess_perror("snmpget", &session); SOCK_CLEANUP; exit(1); } /* * Create PDU for GET request and add object names to request. */ pdu = snmp_pdu_create(SNMP_MSG_GET); for (count = 0; count < current_name; count++) { name_length = MAX_OID_LEN; if (!snmp_parse_oid(names[count], name, &name_length)) { snmp_perror(names[count]); failures++; } else snmp_add_null_var(pdu, name, name_length); } if (failures) { SOCK_CLEANUP; exit(1); } /* * Perform the request. * * If the Get Request fails, note the OID that caused the error, * "fix" the PDU (removing the error-prone OID) and retry. */ retry: status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { struct sockaddr_in *in = response->transport_data; printf ("Peername = %s\n", ss->peername); printf ("Response Address = %lx\n", in->sin_addr.S_un.S_addr); if (response->errstat == SNMP_ERR_NOERROR) { for (vars = response->variables; vars; vars = vars->next_variable) print_variable(vars->name, vars->name_length, vars); } else { fprintf(stderr, "Error in packet\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errindex != 0) { fprintf(stderr, "Failed object: "); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) /*EMPTY*/; if (vars) fprint_objid(stderr, vars->name, vars->name_length); fprintf(stderr, "\n"); } exitval = 2; /* * retry if the errored variable was successfully removed */ if (!ds_get_boolean(DS_APPLICATION_ID, DS_APP_DONT_FIX_PDUS)) { pdu = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; if (pdu != NULL) goto retry; } } /* endif -- SNMP_ERR_NOERROR */ } else if (status == STAT_TIMEOUT) { fprintf(stderr, "Timeout: No Response from %s.\n", session.peername); exitval = 1; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmpget", ss); exitval = 1; } /* endif -- STAT_SUCCESS */ if (response) snmp_free_pdu(response); snmp_close(ss); SOCK_CLEANUP; return exitval; } /* end main() */