/** * snmp_getn_bulk: Builds and sends a SNMP_BET_BULK pdu using snmp * @sessp: snmp session * @bulk_objid: string containing the OID entry. * @bulk_objid_len: len of OID string * @bulk_pdu: pointer to the PDU to be created * @bulk_response: pointer to the response for this PDU request * @num_repetitions: max OIDs for this request. * Note: this is the max requested. Actual number returned can be less * than maximum. That depends on the target snmp agent. * * Return value: status from snmp_sess_synch_response(). See snmp_client.h of net-snmp library. * STAT_SUCCESS * STAT_ERROR * STAT_TIMEOUT * * Additionally, if status == STAT_SUCCESS, consumer of this routine needs to check for exception * conditions. * Possible exception conditions are SNMP_ENDOFMIBVIEW, SNMP_NOSUCHOBJECT, SNMP_NOSUCHINSTANCE **/ int snmp_getn_bulk( void *sessp, oid *bulk_objid, size_t bulk_objid_len, struct snmp_pdu *bulk_pdu, struct snmp_pdu **bulk_response, int num_repetitions ) { int status; bulk_pdu = snmp_pdu_create(SNMP_MSG_GETBULK); bulk_pdu->non_repeaters = 0; bulk_pdu->max_repetitions = num_repetitions; snmp_add_null_var(bulk_pdu, bulk_objid, bulk_objid_len); /* Send the Request out.*/ status = snmp_sess_synch_response(sessp, bulk_pdu, bulk_response); /* * Return the status. Consumer of this util has to process the response. */ return(status); }
/** Write on/off status */ double setMainSwitch(HSNMP m_sessp,float value) { struct snmp_pdu* pdu = snmp_pdu_create(SNMP_MSG_SET); // prepare set-request pdu pdu->community = (u_char*)strdup(writeCommunity); pdu->community_len = strlen(writeCommunity); // for(each SET request to one crate) { int v = (int) value; snmp_pdu_add_variable(pdu,oidSysMainSwitch,lengthSysMainSwitch,ASN_INTEGER,(u_char*)&v,sizeof(v)); // } // endfor struct snmp_pdu* response; int status = snmp_sess_synch_response(m_sessp,pdu,&response); /* * Process the response. */ if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { /* * SUCCESS: Print the result variables */ struct variable_list *vars; // debug print //for(vars = response->variables; vars; vars = vars->next_variable) // print_variable(vars->name, vars->name_length, vars); /* manipuate the information ourselves */ for(vars = response->variables; vars; vars = vars->next_variable) { if (vars->type == ASN_OPAQUE_FLOAT) { // 0x78 value = *vars->val.floatVal; } else if (vars->type == ASN_OPAQUE_DOUBLE) { // 0x79 value = *vars->val.doubleVal; } else if(vars->type == ASN_INTEGER) { // 0x02 value = (double)*vars->val.integer; } } } else { /* * FAILURE: print what went wrong! */ if (status == STAT_SUCCESS) fprintf(stderr, "Error in packet\nReason: %s\n", snmp_errstring(response->errstat)); else snmp_sess_perror("snmpget",snmp_sess_session(m_sessp)); return 0; } snmp_free_pdu(response); return value; }
/** Get current from power supply */ double getCurrentMeasurement(HSNMP m_sessp, int channel) { double value; struct snmp_pdu* pdu = snmp_pdu_create(SNMP_MSG_GET); // prepare get-request pdu // for(each GET request to one crate) { snmp_add_null_var(pdu,oidOutputMeasurementCurrent[channel],lengthOutputMeasurementCurrent[channel]); // generate request data // } // endfor struct snmp_pdu* response; int status = snmp_sess_synch_response(m_sessp,pdu,&response); /* * Process the response. */ if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { /* * SUCCESS: Print the result variables */ struct variable_list *vars; // debug print //for(vars = response->variables; vars; vars = vars->next_variable) // print_variable(vars->name, vars->name_length, vars); /* manipuate the information ourselves */ for(vars = response->variables; vars; vars = vars->next_variable) { if (vars->type == ASN_OPAQUE_FLOAT) { // 0x78 value = *vars->val.floatVal; } else if (vars->type == ASN_OPAQUE_DOUBLE) { // 0x79 value = *vars->val.doubleVal; } else if(vars->type == ASN_INTEGER) { // 0x02 value = (double)*vars->val.integer; } } } else { /* * FAILURE: print what went wrong! */ if (status == STAT_SUCCESS) fprintf(stderr, "Error in packet\nReason: %s\n", snmp_errstring(response->errstat)); else snmp_sess_perror("snmpget",snmp_sess_session(m_sessp)); return 0; } snmp_free_pdu(response); return value; }
/** Get channel status */ int getChannelStatus(HSNMP m_sessp, int channel) { double value; struct snmp_pdu* pdu = snmp_pdu_create(SNMP_MSG_GET); // prepare get-request pdu // for(each GET request to one crate) { snmp_add_null_var(pdu,oidOutputStatus[channel],lengthOutputStatus[channel]); // generate request data // } // endfor struct snmp_pdu* response; int status = snmp_sess_synch_response(m_sessp,pdu,&response); /* * Process the response. */ if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { /* * SUCCESS: Print the result variables */ struct variable_list *vars; // debug print //for(vars = response->variables; vars; vars = vars->next_variable) // print_variable(vars->name, vars->name_length, vars); /* manipuate the information ourselves */ for(vars = response->variables; vars; vars = vars->next_variable) { if (vars->type == ASN_OPAQUE_FLOAT) { // 0x78 value = *vars->val.floatVal; } else if (vars->type == ASN_OPAQUE_DOUBLE) { // 0x79 value = *vars->val.doubleVal; } else if(vars->type == ASN_INTEGER) { // 0x02 value = (double)*vars->val.integer; } else if(vars->type == ASN_OCTET_STR) { // 0x04 unsigned long bitstring = 0; for(int cpos = vars->val_len-1;cpos >= 0;cpos--) { unsigned char octet = vars->val.string[cpos]; for(int bpos = 0;bpos < 8;bpos++) { // convert one character bitstring <<= 1; if(octet&0x01) bitstring |= 1; octet >>= 1; } } value = bitstring; } } } else {
SaErrorT snmp_getn_bulk( void *sessp, oid *bulk_objid, size_t bulk_objid_len, struct snmp_pdu *bulk_pdu, struct snmp_pdu **bulk_response, int num_repetitions ) { int status; SaErrorT rtncode = SA_OK; // struct variable_list *vars; bulk_pdu = snmp_pdu_create(SNMP_MSG_GETBULK); bulk_pdu->non_repeaters = 0; bulk_pdu->max_repetitions = num_repetitions; snmp_add_null_var(bulk_pdu, bulk_objid, bulk_objid_len); /* Send the Request out.*/ status = snmp_sess_synch_response(sessp, bulk_pdu, bulk_response); /* * Process the response. */ #if 0 if (status == STAT_SUCCESS) { vars = (*bulk_response)->variables; if ((*bulk_response)->errstat == SNMP_ERR_NOERROR) { if (!CHECH_END(vars->type)) { /* This is one of the exception condition */ rtncode = SA_ERR_HPI_NOT_PRESENT; dbg("snmp exception %d \n",vars->type); } } else { fprintf(stderr, "Error in packet %s\nReason: %s\n", (char *)bulk_objid, snmp_errstring((*bulk_response)->errstat)); if ((*bulk_response)->errstat == SNMP_ERR_NOSUCHNAME) (*bulk_response)->errstat = SNMP_NOSUCHOBJECT; rtncode = (SaErrorT) (SA_ERR_SNMP_BASE - (*bulk_response)->errstat); } } else { snmp_sess_perror("snmpset", ss); rtncode = (SaErrorT) (SA_ERR_SNMP_BASE - status); } #endif return(rtncode); }
// request executes an SNMP GETBULK request. char *request(void *sessp, long max_repetitions, oid *name, size_t name_length, struct snmp_pdu **response) { struct snmp_pdu *request = snmp_pdu_create(SNMP_MSG_GETBULK); request->non_repeaters = NON_REPEATERS; request->max_repetitions = max_repetitions; snmp_add_null_var(request, name, name_length); int status = snmp_sess_synch_response(sessp, request, response); if (status != STAT_SUCCESS) { char *errstr = session_error(sessp); char *err = NULL; int failure = asprintf(&err, "SNMP request error: %s", errstr); if (failure == -1) { err = errstr; } else { free(errstr); } return err; } return NULL; }
/** * snmp_get * @ss: a handle to the snmp session needed to make an * snmp transaction. * @objid: string containing the OID entry. * @value: the value received from snmp will be put in this union. * * Gets a single value indicated by the objectid using snmp. * In the case of multiple values being returned, the type in @value will be * ASN_NULL (0x05). Nothing else in @value will be filled in. * * Returns: 0 if successful, <0 if there was an error. **/ SaErrorT snmp_get( void *sessp, const char *objid, struct snmp_value *value) { struct snmp_pdu *pdu; struct snmp_pdu *response; struct snmp_session *session; oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; struct variable_list *vars; SaErrorT returncode = SA_OK; int status; /* * Create the PDU for the data for our request. */ pdu = snmp_pdu_create(SNMP_MSG_GET); read_objid(objid, anOID, &anOID_len); snmp_add_null_var(pdu, anOID, anOID_len); /* * Send the Request out. */ status = snmp_sess_synch_response(sessp, pdu, &response); /* * Process the response. */ if (status == STAT_SUCCESS) { if(response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; value->type = vars->type; if (vars->next_variable != NULL) { /* There are more values, set return type to null. */ value->type = ASN_NULL; } else if ( !(CHECK_END(vars->type)) ) { /* This is one of the exception condition */ returncode = SA_ERR_HPI_NOT_PRESENT; dbg("snmp exception %d \n",vars->type); dbg("OID=%s", objid); } else if ( (vars->type == ASN_INTEGER) || (vars->type == ASN_COUNTER) || (vars->type == ASN_UNSIGNED) ) { value->integer = *(vars->val.integer); } else { value->str_len = vars->val_len; if (value->str_len >= MAX_ASN_STR_LEN) value->str_len = MAX_ASN_STR_LEN; else value->string[value->str_len] = '\0'; memcpy(value->string, vars->val.string, value->str_len); } } else { dbg("Error in packet %s\nReason: %s\n", objid, snmp_errstring(response->errstat)); returncode = errstat2hpi(response->errstat); } } else { value->type = (u_char)0x00; session = snmp_sess_session(sessp); snmp_sess_perror("snmpget", session); dbg("OID=%s", objid); returncode = snmpstat2hpi(status); } /* Clean up: free the response */ if (response) snmp_free_pdu(response); return (returncode); }
/*! \fn char *snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) * \brief performs multiple OID snmp_get's in a single network call * * This function will a group of snmp OID's for a host. The host snmp * session must already be established. The function will modify elements of * the snmp_oids array with the results from the snmp api call. * */ void snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) { struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; struct variable_list *vars = NULL; int status; int i; int max_repetitions = 1; int non_repeaters = 0; struct nameStruct { oid name[MAX_OID_LEN]; size_t name_len; } *name, *namep; /* load up oids */ namep = name = (struct nameStruct *) calloc(num_oids, sizeof(*name)); pdu = snmp_pdu_create(SNMP_MSG_GET); for (i = 0; i < num_oids; i++) { namep->name_len = MAX_OID_LEN; if (!snmp_parse_oid(snmp_oids[i].oid, namep->name, &namep->name_len)) { CACTID_LOG(("Host[%i] ERROR: Problems parsing Multi SNMP OID! (oid: %s)\n", current_host->id, snmp_oids[i].oid)); /* Mark this OID as "bad" */ SET_UNDEFINED(snmp_oids[i].result); }else{ snmp_add_null_var(pdu, namep->name, namep->name_len); } namep++; } status = STAT_DESCRIP_ERROR; /* execute the multi-get request */ retry: status = snmp_sess_synch_response(current_host->snmp_session, pdu, &response); /* liftoff, successful poll, process it!! */ if (status == STAT_SUCCESS) { if (response == NULL) { CACTID_LOG(("ERROR: An internal Net-Snmp error condition detected in Cacti snmp_get_multi\n")); status = STAT_ERROR; }else{ if (response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; for(i = 0; i < num_oids && vars; i++) { if (!IS_UNDEFINED(snmp_oids[i].result)) { #ifdef USE_NET_SNMP snmp_snprint_value(snmp_oids[i].result, sizeof(snmp_oids[i].result), vars->name, vars->name_length, vars); #else sprint_value(snmp_oids[i].result, vars->name, vars->name_length, vars); #endif vars = vars->next_variable; } } }else{ if (response->errindex != 0) { /* removed errored OID and then retry */ int count; /* Find our index against errindex */ count = 0; for(i = 0; i < num_oids && count < response->errindex; i++) { if ( ! IS_UNDEFINED(snmp_oids[i].result) ) { count++; } } i--; SET_UNDEFINED(snmp_oids[i].result); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) { } pdu = snmp_fix_pdu(response, SNMP_MSG_GET); snmp_free_pdu(response); response = NULL; if (pdu != NULL) { goto retry; }else{ status = STAT_DESCRIP_ERROR; } }else{ status = STAT_DESCRIP_ERROR; } } } } if (status != STAT_SUCCESS) { current_host->ignore_host = 1; for (i = 0; i < num_oids; i++) { SET_UNDEFINED(snmp_oids[i].result); } } if (response != NULL) { snmp_free_pdu(response); } }
void *poller(void *thread_args) { worker_t *worker = (worker_t *) thread_args; crew_t *crew = worker->crew; target_t *entry = NULL; void *sessp = NULL; struct snmp_session session; struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; struct variable_list *vars = NULL; unsigned long long result = 0; unsigned long long last_value = 0; unsigned long long insert_val = 0; int poll_status = 0, db_status = 0, bits = 0, init = 0; char query[BUFSIZE]; char storedoid[BUFSIZE]; char result_string[BUFSIZE]; int cur_work = 0; int prev_work = 99999999; int loop_count = 0; #ifdef FEATURES /* Per thread SQL connection testing */ #if HAVE_MYSQL MYSQL mysql; #elif HAVE_PGSQL PGconn *pgsql; #endif double rate = 0; struct timezone tzp; struct timeval current_time; struct timeval last_time; /* for thread settings */ int oldstate, oldtype; #endif debug(HIGH, "Thread [%d] starting.\n", worker->index); pthread_cleanup_push(cleanup_db, NULL); /* Attempt to connect to the MySQL Database */ #ifdef FEATURES /* Per thread MySQL connection testing */ if (!(set->dboff)) { /* load the database driver */ if (!(db_init(set))) { fatal("** Database error - check configuration.\n"); } /* connect to the database */ if (!(db_connect(set))) { fatal("server not responding.\n"); } /* set up cancel function for exit */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); } #endif /* FEATURES */ while (1) { /* if(loop_count >= POLLS_PER_TRANSACTION) { debug(HIGH, "Thread [%d] doing commit on %d\n", worker->index, POLLS_PER_TRANSACTION); db_status = db_commit(); loop_count = 0; } */ #ifdef FEATURES /* see if we've been cancelled before we start another loop */ pthread_testcancel(); #endif debug(DEVELOP, "Thread [%d] locking (wait on work)\n", worker->index); PT_MUTEX_LOCK(&crew->mutex); #ifdef FEATURES /* add an unlock to the cancel stack */ pthread_cleanup_push(cancel_lock, &crew->mutex); #endif while (current == NULL) { PT_COND_WAIT(&crew->go, &crew->mutex); } debug(DEVELOP, "Thread [%d] done waiting, received go (work cnt: %d)\n", worker->index, crew->work_count); cur_work = crew->work_count; /* if(cur_work > prev_work) { debug(HIGH, "Thread [%d] doing commit at %d\n", worker->index,time(NULL)); db_status = db_commit(); loop_count = 0; } */ prev_work = cur_work; if (current != NULL) { debug(DEVELOP, "Thread [%d] processing %s %s (%d work units remain in queue)\n", worker->index, current->host->host, current->objoid, crew->work_count); snmp_enable_stderrlog(); snmp_sess_init(&session); if (current->host->snmp_ver == 2) session.version = SNMP_VERSION_2c; else session.version = SNMP_VERSION_1; session.peername = current->host->host; session.community = current->host->community; session.remote_port = set->snmp_port; session.community_len = strlen(session.community); sessp = snmp_sess_open(&session); anOID_len = MAX_OID_LEN; pdu = snmp_pdu_create(SNMP_MSG_GET); read_objid(current->objoid, anOID, &anOID_len); entry = current; last_value = current->last_value; #ifdef FEATURES /* save the time so we can calculate rate */ last_time = current->last_time; #endif init = current->init; insert_val = 0; bits = current->bits; strncpy(storedoid, current->objoid, sizeof(storedoid)); current = getNext(); } debug(DEVELOP, "Thread [%d] unlocking (done grabbing current)\n", worker->index); PT_MUTEX_UNLOCK(&crew->mutex); #ifdef FEATURES /* take the unlock off the cancel stack */ pthread_cleanup_pop(FALSE); #endif snmp_add_null_var(pdu, anOID, anOID_len); if (sessp != NULL) poll_status = snmp_sess_synch_response(sessp, pdu, &response); else poll_status = STAT_DESCRIP_ERROR; /* Collect response and process stats */ PT_MUTEX_LOCK(&stats.mutex); if (poll_status == STAT_DESCRIP_ERROR) { stats.errors++; printf("*** SNMP Error: (%s) Bad descriptor.\n", session.peername); } else if (poll_status == STAT_TIMEOUT) { stats.no_resp++; printf("*** SNMP No response: (%s@%s).\n", session.peername, storedoid); } else if (poll_status != STAT_SUCCESS) { stats.errors++; printf("*** SNMP Error: (%s@%s) Unsuccessuful (%d).\n", session.peername, storedoid, poll_status); } else if (poll_status == STAT_SUCCESS && response->errstat != SNMP_ERR_NOERROR) { stats.errors++; printf("*** SNMP Error: (%s@%s) %s\n", session.peername, storedoid, snmp_errstring(response->errstat)); } else if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR && response->variables->type == SNMP_NOSUCHINSTANCE) { stats.errors++; printf("*** SNMP Error: No Such Instance Exists (%s@%s)\n", session.peername, storedoid); } else if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { stats.polls++; } PT_MUTEX_UNLOCK(&stats.mutex); /* Liftoff, successful poll, process it */ #ifdef FEATURES /* Get the current time */ gettimeofday(¤t_time, &tzp); #endif if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR && response->variables->type != SNMP_NOSUCHINSTANCE) { vars = response->variables; #ifdef OLD_UCD_SNMP sprint_value(result_string, anOID, anOID_len, vars); #else snprint_value(result_string, BUFSIZE, anOID, anOID_len, vars); #endif switch (vars->type) { /* * Switch over vars->type and modify/assign result accordingly. */ case ASN_COUNTER64: debug(DEBUG, "64-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = vars->val.counter64->high; result = result << 32; result = result + vars->val.counter64->low; break; case ASN_COUNTER: debug(DEBUG, "32-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_INTEGER: debug(DEBUG, "Integer result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_GAUGE: debug(DEBUG, "32-bit gauge: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_TIMETICKS: debug(DEBUG, "Timeticks result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_OPAQUE: debug(DEBUG, "Opaque result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_OCTET_STR: debug(DEBUG, "String Result: (%s@%s) %s\n", session.peername, storedoid, result_string); #ifdef HAVE_STRTOLL result = strtoll(vars->val.string, NULL, 0); #else result = strtol(vars->val.string, NULL, 0); #endif break; default: debug(LOW, "Unknown result type: (%s@%s) %s\n", session.peername, storedoid, result_string); } /* Gauge Type */ if (bits == 0) { if (result != last_value) { insert_val = result; debug(DEVELOP, "Thread [%d]: Gauge change from %lld to %lld\n", worker->index, last_value, insert_val); } else { if (set->withzeros) insert_val = result; debug(DEVELOP, "Thread [%d]: Gauge steady at %lld\n", worker->index, insert_val); } /* Counter Wrap Condition */ } else if (result < last_value) { PT_MUTEX_LOCK(&stats.mutex); stats.wraps++; PT_MUTEX_UNLOCK(&stats.mutex); if (bits == 32) insert_val = (THIRTYTWO - last_value) + result; else if (bits == 64) insert_val = (SIXTYFOUR - last_value) + result; #ifdef FEATURES rate = insert_val / timediff(current_time, last_time); #endif debug(LOW, "*** Counter Wrap (%s@%s) [poll: %llu][last: %llu][insert: %llu]\n", session.peername, storedoid, result, last_value, insert_val); /* Not a counter wrap and this is not the first poll */ } else if ((last_value >= 0) && (init != NEW)) { insert_val = result - last_value; #ifdef FEATURES rate = insert_val / timediff(current_time, last_time); #endif /* Print out SNMP result if verbose */ if (set->verbose == DEBUG) printf("Thread [%d]: (%lld-%lld -- %llu) = %llu\n", worker->index, result, last_value, insert_val,rate); if (set->verbose == HIGH) printf("Thread [%d]: %llu\n", worker->index, insert_val); /* last_value < 0, so this must be the first poll */ } else { #ifdef FEATURES /* set up this result for the next poll */ entry->last_value = result; #endif debug(HIGH, "Thread [%d]: First Poll, Normalizing\n", worker->index); } /* Check for bogus data, either negative or unrealistic */ if (insert_val > entry->maxspeed || result < 0) { debug(LOW, "*** Out of Range (%s@%s) [insert_val: %llu] [oor: %lld]\n", session.peername, storedoid, insert_val, entry->maxspeed); insert_val = 0; #ifdef FEATURES rate = 0; #endif PT_MUTEX_LOCK(&stats.mutex); stats.out_of_range++; PT_MUTEX_UNLOCK(&stats.mutex); } if (!(set->dboff)) { if ( (insert_val > 0) || (set->withzeros) ) { #ifndef FEATURES /* MP - since we have our own database connection we don't need to lock it anymore */ PT_MUTEX_LOCK(&crew->mutex); #endif debug(DEVELOP, "db_insert sent: %s %d %d %e\n",entry->table,entry->iid,insert_val,rate); /* insert into the database */ db_status = db_insert(entry->table, entry->iid, insert_val, rate); #ifndef FEATURES /* MP - since we have our own database connection we don't need to lock it anymore */ PT_MUTEX_UNLOCK(&crew->mutex); #endif if (db_status) { PT_MUTEX_LOCK(&stats.mutex); stats.db_inserts++; PT_MUTEX_UNLOCK(&stats.mutex); } else { fatal("Fatal database error.\n"); } } /* insert_val > 0 or withzeros */ } /* !dboff */ } /* STAT_SUCCESS */ /* debug(HIGH, "Thread [%d] doing commit\n", worker->index); db_status = db_commit(); */ if (sessp != NULL) { snmp_sess_close(sessp); if (response != NULL) snmp_free_pdu(response); } debug(DEVELOP, "Thread [%d] locking (update work_count)\n", worker->index); PT_MUTEX_LOCK(&crew->mutex); crew->work_count--; /* Only if we received a positive result back do we update the last_value object */ if (poll_status == STAT_SUCCESS) { entry->last_value = result; if (init == NEW) entry->init = LIVE; } #ifdef FEATURES /* always update the time */ entry->last_time = current_time; #endif if (crew->work_count <= 0) { debug(HIGH, "Queue processed. Broadcasting thread done condition.\n"); PT_COND_BROAD(&crew->done); } debug(DEVELOP, "Thread [%d] unlocking (update work_count)\n", worker->index); PT_MUTEX_UNLOCK(&crew->mutex); loop_count++; } /* while(1) */ pthread_cleanup_pop(FALSE); /* Not reached */ }
/*! \fn char *snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) * \brief performs multiple OID snmp_get's in a single network call * * This function will a group of snmp OID's for a host. The host snmp * session must already be established. The function will modify elements of * the snmp_oids array with the results from the snmp api call. * */ void snmp_get_multi(host_t *current_host, snmp_oids_t *snmp_oids, int num_oids) { struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; struct variable_list *vars = NULL; int status; int i; int max_repetitions = 1; int non_repeaters = 0; int array_count; int index_count; /* get rid of some compiler warnings */ errstat = 0; errindex = 0; struct nameStruct { oid name[MAX_OID_LEN]; size_t name_len; } *name, *namep; /* load up oids */ namep = name = (struct nameStruct *) calloc(num_oids, sizeof(*name)); pdu = snmp_pdu_create(SNMP_MSG_GET); for (i = 0; i < num_oids; i++) { namep->name_len = MAX_OID_LEN; if (!snmp_parse_oid(snmp_oids[i].oid, namep->name, &namep->name_len)) { SPINE_LOG(("Host[%i] ERROR: Problems parsing Multi SNMP OID! (oid: %s)\n", current_host->id, snmp_oids[i].oid)); /* Mark this OID as "bad" */ SET_UNDEFINED(snmp_oids[i].result); }else{ snmp_add_null_var(pdu, namep->name, namep->name_len); } namep++; } status = STAT_DESCRIP_ERROR; /* execute the multi-get request */ retry: status = snmp_sess_synch_response(current_host->snmp_session, pdu, &response); /* liftoff, successful poll, process it!! */ if (status == STAT_SUCCESS) { if (response == NULL) { SPINE_LOG(("ERROR: An internal Net-Snmp error condition detected in Cacti snmp_get_multi\n")); status = STAT_ERROR; }else{ if (response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; for(i = 0; i < num_oids && vars; i++) { if (!IS_UNDEFINED(snmp_oids[i].result)) { #ifdef USE_NET_SNMP snmp_snprint_value(snmp_oids[i].result, RESULTS_BUFFER, vars->name, vars->name_length, vars); #else sprint_value(snmp_oids[i].result, vars->name, vars->name_length, vars); #endif vars = vars->next_variable; } } }else{ if (response->errindex != 0) { index_count = 1; array_count = 0; /* Find our index against errindex */ while (array_count < num_oids) { if (IS_UNDEFINED(snmp_oids[array_count].result) ) { array_count++; }else{ /* if we have found our error, exit */ if (index_count == response->errindex) { SET_UNDEFINED(snmp_oids[array_count].result); break; } array_count++; index_count++; } } /* remote the invalid OID from the PDU */ pdu = snmp_fix_pdu(response, SNMP_MSG_GET); /* free the previous response */ snmp_free_pdu(response); response = NULL; if (pdu != NULL) { /* retry the request */ goto retry; }else{ /* all OID's errored out so exit cleanly */ status = STAT_SUCCESS; } }else{ status = STAT_DESCRIP_ERROR; } } } } if (status != STAT_SUCCESS) { current_host->ignore_host = 1; for (i = 0; i < num_oids; i++) { SET_UNDEFINED(snmp_oids[i].result); } } if (response != NULL) { snmp_free_pdu(response); } }
/*! \fn char *snmp_getnext(host_t *current_host, char *snmp_oid) * \brief performs a single snmp_getnext for a specific snmp OID * * This function will poll a specific snmp OID for a host. The host snmp * session must already be established. * * \return returns the character representaton of the snmp OID, or "U" if * unsuccessful. * */ char *snmp_getnext(host_t *current_host, char *snmp_oid) { struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; struct variable_list *vars = NULL; size_t anOID_len = MAX_OID_LEN; oid anOID[MAX_OID_LEN]; int status; char *result_string; if (!(result_string = (char *) malloc(RESULTS_BUFFER))) { die("ERROR: Fatal malloc error: snmp.c snmp_get!"); } result_string[0] = '\0'; status = STAT_DESCRIP_ERROR; if (current_host->snmp_session != NULL) { anOID_len = MAX_OID_LEN; pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); if (!snmp_parse_oid(snmp_oid, anOID, &anOID_len)) { SPINE_LOG(("ERROR: Problems parsing SNMP OID\n")); SET_UNDEFINED(result_string); return result_string; }else{ snmp_add_null_var(pdu, anOID, anOID_len); } /* poll host */ status = snmp_sess_synch_response(current_host->snmp_session, pdu, &response); /* liftoff, successful poll, process it!! */ if (status == STAT_SUCCESS) { if (response == NULL) { SPINE_LOG(("ERROR: An internal Net-Snmp error condition detected in Cacti snmp_get\n")); SET_UNDEFINED(result_string); status = STAT_ERROR; }else{ if (response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; #ifdef USE_NET_SNMP snprint_value(result_string, RESULTS_BUFFER, anOID, anOID_len, vars); #else sprint_value(result_string, anOID, anOID_len, vars); #endif } } } if (response) { snmp_free_pdu(response); response = NULL; } }else{ status = STAT_DESCRIP_ERROR; } if (status != STAT_SUCCESS) { current_host->ignore_host = TRUE; SET_UNDEFINED(result_string); } return result_string; }
static int csnmp_read_value (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; struct snmp_pdu *res; struct variable_list *vb; const data_set_t *ds; value_list_t vl = VALUE_LIST_INIT; int status; size_t i; DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { DEBUG ("snmp plugin: csnmp_read_value: host->sess_handle == NULL"); return (-1); } ds = plugin_get_ds (data->type); if (!ds) { ERROR ("snmp plugin: DataSet `%s' not defined.", data->type); return (-1); } if (ds->ds_num != data->values_len) { ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu", data->type, ds->ds_num, data->values_len); return (-1); } vl.values_len = ds->ds_num; vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len); if (vl.values == NULL) return (-1); for (i = 0; i < vl.values_len; i++) { if (ds->ds[i].type == DS_TYPE_COUNTER) vl.values[i].counter = 0; else vl.values[i].gauge = NAN; } sstrncpy (vl.host, host->name, sizeof (vl.host)); sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin)); sstrncpy (vl.type, data->type, sizeof (vl.type)); sstrncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance)); vl.interval = host->interval; req = snmp_pdu_create (SNMP_MSG_GET); if (req == NULL) { ERROR ("snmp plugin: snmp_pdu_create failed."); sfree (vl.values); return (-1); } for (i = 0; i < data->values_len; i++) snmp_add_null_var (req, data->values[i].oid, data->values[i].oid_len); res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); ERROR ("snmp plugin: host %s: snmp_sess_synch_response failed: %s", host->name, (errstr == NULL) ? "Unknown problem" : errstr); if (res != NULL) snmp_free_pdu (res); res = NULL; sfree (errstr); csnmp_host_close_session (host); return (-1); } for (vb = res->variables; vb != NULL; vb = vb->next_variable) { #if COLLECT_DEBUG char buffer[1024]; snprint_variable (buffer, sizeof (buffer), vb->name, vb->name_length, vb); DEBUG ("snmp plugin: Got this variable: %s", buffer); #endif /* COLLECT_DEBUG */ for (i = 0; i < data->values_len; i++) if (snmp_oid_compare (data->values[i].oid, data->values[i].oid_len, vb->name, vb->name_length) == 0) vl.values[i] = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift, host->name, data->name); } /* for (res->variables) */ if (res != NULL) snmp_free_pdu (res); res = NULL; DEBUG ("snmp plugin: -> plugin_dispatch_values (&vl);"); plugin_dispatch_values (&vl); sfree (vl.values); return (0); } /* int csnmp_read_value */
static int csnmp_read_table (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; struct snmp_pdu *res; struct variable_list *vb; const data_set_t *ds; size_t oid_list_len = data->values_len + 1; /* Holds the last OID returned by the device. We use this in the GETNEXT * request to proceed. */ oid_t oid_list[oid_list_len]; /* Set to false when an OID has left its subtree so we don't re-request it * again. */ _Bool oid_list_todo[oid_list_len]; int status; size_t i; /* `value_list_head' and `value_list_tail' implement a linked list for each * value. `instance_list_head' and `instance_list_tail' implement a linked list of * instance names. This is used to jump gaps in the table. */ csnmp_list_instances_t *instance_list_head; csnmp_list_instances_t *instance_list_tail; csnmp_table_values_t **value_list_head; csnmp_table_values_t **value_list_tail; DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL"); return (-1); } ds = plugin_get_ds (data->type); if (!ds) { ERROR ("snmp plugin: DataSet `%s' not defined.", data->type); return (-1); } if (ds->ds_num != data->values_len) { ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu", data->type, ds->ds_num, data->values_len); return (-1); } assert (data->values_len > 0); /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); if (data->instance.oid.oid_len > 0) memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t)); else /* no InstanceFrom option specified. */ oid_list_len--; for (i = 0; i < oid_list_len; i++) oid_list_todo[i] = 1; /* We're going to construct n linked lists, one for each "value". * value_list_head will contain pointers to the heads of these linked lists, * value_list_tail will contain pointers to the tail of the lists. */ value_list_head = calloc (data->values_len, sizeof (*value_list_head)); value_list_tail = calloc (data->values_len, sizeof (*value_list_tail)); if ((value_list_head == NULL) || (value_list_tail == NULL)) { ERROR ("snmp plugin: csnmp_read_table: calloc failed."); sfree (value_list_head); sfree (value_list_tail); return (-1); } instance_list_head = NULL; instance_list_tail = NULL; status = 0; while (status == 0) { int oid_list_todo_num; req = snmp_pdu_create (SNMP_MSG_GETNEXT); if (req == NULL) { ERROR ("snmp plugin: snmp_pdu_create failed."); status = -1; break; } oid_list_todo_num = 0; for (i = 0; i < oid_list_len; i++) { /* Do not rerequest already finished OIDs */ if (!oid_list_todo[i]) continue; oid_list_todo_num++; snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len); } if (oid_list_todo_num == 0) { /* The request is still empty - so we are finished */ DEBUG ("snmp plugin: all variables have left their subtree"); status = 0; break; } res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); c_complain (LOG_ERR, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response failed: %s", host->name, (errstr == NULL) ? "Unknown problem" : errstr); if (res != NULL) snmp_free_pdu (res); res = NULL; /* snmp_synch_response already freed our PDU */ req = NULL; sfree (errstr); csnmp_host_close_session (host); status = -1; break; } status = 0; assert (res != NULL); c_release (LOG_INFO, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response successful.", host->name); vb = res->variables; if (vb == NULL) { status = -1; break; } for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++) { /* Calculate value index from todo list */ while ((i < oid_list_len) && !oid_list_todo[i]) i++; /* An instance is configured and the res variable we process is the * instance value (last index) */ if ((data->instance.oid.oid_len > 0) && (i == data->values_len)) { if ((vb->type == SNMP_ENDOFMIBVIEW) || (snmp_oid_ncompare (data->instance.oid.oid, data->instance.oid.oid_len, vb->name, vb->name_length, data->instance.oid.oid_len) != 0)) { DEBUG ("snmp plugin: host = %s; data = %s; Instance left its subtree.", host->name, data->name); oid_list_todo[i] = 0; continue; } /* Allocate a new `csnmp_list_instances_t', insert the instance name and * add it to the list */ if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail, res, host, data) != 0) { ERROR ("snmp plugin: host %s: csnmp_instance_list_add failed.", host->name); status = -1; break; } } else /* The variable we are processing is a normal value */ { csnmp_table_values_t *vt; oid_t vb_name; oid_t suffix; int ret; csnmp_oid_init (&vb_name, vb->name, vb->name_length); /* Calculate the current suffix. This is later used to check that the * suffix is increasing. This also checks if we left the subtree */ ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i); if (ret != 0) { DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; " "Value probably left its subtree.", host->name, data->name, i); oid_list_todo[i] = 0; continue; } /* Make sure the OIDs returned by the agent are increasing. Otherwise our * table matching algorithm will get confused. */ if ((value_list_tail[i] != NULL) && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0)) { DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; " "Suffix is not increasing.", host->name, data->name, i); oid_list_todo[i] = 0; continue; } vt = malloc (sizeof (*vt)); if (vt == NULL) { ERROR ("snmp plugin: malloc failed."); status = -1; break; } memset (vt, 0, sizeof (*vt)); vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift, host->name, data->name); memcpy (&vt->suffix, &suffix, sizeof (vt->suffix)); vt->next = NULL; if (value_list_tail[i] == NULL) value_list_head[i] = vt; else value_list_tail[i]->next = vt; value_list_tail[i] = vt; } /* Copy OID to oid_list[i] */ memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[i].oid_len = vb->name_length; } /* for (vb = res->variables ...) */ if (res != NULL) snmp_free_pdu (res); res = NULL; } /* while (status == 0) */ if (res != NULL) snmp_free_pdu (res); res = NULL; if (req != NULL) snmp_free_pdu (req); req = NULL; if (status == 0) csnmp_dispatch_table (host, data, instance_list_head, value_list_head); /* Free all allocated variables here */ while (instance_list_head != NULL) { csnmp_list_instances_t *next = instance_list_head->next; sfree (instance_list_head); instance_list_head = next; } for (i = 0; i < data->values_len; i++) { while (value_list_head[i] != NULL) { csnmp_table_values_t *next = value_list_head[i]->next; sfree (value_list_head[i]); value_list_head[i] = next; } } sfree (value_list_head); sfree (value_list_tail); return (0); } /* int csnmp_read_table */
static int csnmp_read_table (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; struct snmp_pdu *res; struct variable_list *vb; const data_set_t *ds; oid_t *oid_list; uint32_t oid_list_len; int status; int i; /* `value_table' and `value_table_ptr' implement a linked list for each * value. `instance_list' and `instance_list_ptr' implement a linked list of * instance names. This is used to jump gaps in the table. */ csnmp_list_instances_t *instance_list; csnmp_list_instances_t *instance_list_ptr; csnmp_table_values_t **value_table; csnmp_table_values_t **value_table_ptr; DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL"); return (-1); } ds = plugin_get_ds (data->type); if (!ds) { ERROR ("snmp plugin: DataSet `%s' not defined.", data->type); return (-1); } if (ds->ds_num != data->values_len) { ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i", data->type, ds->ds_num, data->values_len); return (-1); } /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ oid_list_len = data->values_len + 1; oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len)); if (oid_list == NULL) { ERROR ("snmp plugin: csnmp_read_table: malloc failed."); return (-1); } memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); if (data->instance.oid.oid_len > 0) memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t)); else oid_list_len--; /* Allocate the `value_table' */ value_table = (csnmp_table_values_t **) malloc (sizeof (csnmp_table_values_t *) * 2 * data->values_len); if (value_table == NULL) { ERROR ("snmp plugin: csnmp_read_table: malloc failed."); sfree (oid_list); return (-1); } memset (value_table, '\0', sizeof (csnmp_table_values_t *) * 2 * data->values_len); value_table_ptr = value_table + data->values_len; instance_list = NULL; instance_list_ptr = NULL; status = 0; while (status == 0) { req = snmp_pdu_create (SNMP_MSG_GETNEXT); if (req == NULL) { ERROR ("snmp plugin: snmp_pdu_create failed."); status = -1; break; } for (i = 0; (uint32_t) i < oid_list_len; i++) snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len); res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); c_complain (LOG_ERR, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response failed: %s", host->name, (errstr == NULL) ? "Unknown problem" : errstr); if (res != NULL) snmp_free_pdu (res); res = NULL; sfree (errstr); csnmp_host_close_session (host); status = -1; break; } status = 0; assert (res != NULL); c_release (LOG_INFO, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response successful.", host->name); vb = res->variables; if (vb == NULL) { status = -1; break; } /* Check if all values (and possibly the instance) have left their * subtree */ if (csnmp_check_res_left_subtree (host, data, res) != 0) { status = 0; break; } /* if an instance-OID is configured.. */ if (data->instance.oid.oid_len > 0) { /* Allocate a new `csnmp_list_instances_t', insert the instance name and * add it to the list */ if (csnmp_instance_list_add (&instance_list, &instance_list_ptr, res) != 0) { ERROR ("snmp plugin: csnmp_instance_list_add failed."); status = -1; break; } /* Set vb on the last variable */ for (vb = res->variables; (vb != NULL) && (vb->next_variable != NULL); vb = vb->next_variable) /* do nothing */; assert (vb != NULL); /* Copy OID to oid_list[data->values_len] */ memcpy (oid_list[data->values_len].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[data->values_len].oid_len = vb->name_length; } for (vb = res->variables, i = 0; (vb != NULL) && (i < data->values_len); vb = vb->next_variable, i++) { csnmp_table_values_t *vt; /* Check if we left the subtree */ if (snmp_oid_ncompare (data->values[i].oid, data->values[i].oid_len, vb->name, vb->name_length, data->values[i].oid_len) != 0) { DEBUG ("snmp plugin: host = %s; data = %s; Value %i left its subtree.", host->name, data->name, i); continue; } if ((value_table_ptr[i] != NULL) && (vb->name[vb->name_length - 1] <= value_table_ptr[i]->subid)) { DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " "SUBID is not increasing.", host->name, data->name, i); continue; } vt = (csnmp_table_values_t *) malloc (sizeof (csnmp_table_values_t)); if (vt == NULL) { ERROR ("snmp plugin: malloc failed."); status = -1; break; } vt->subid = vb->name[vb->name_length - 1]; vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift); vt->next = NULL; if (value_table_ptr[i] == NULL) value_table[i] = vt; else value_table_ptr[i]->next = vt; value_table_ptr[i] = vt; /* Copy OID to oid_list[i + 1] */ memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[i].oid_len = vb->name_length; } /* for (i = data->values_len) */ if (res != NULL) snmp_free_pdu (res); res = NULL; } /* while (status == 0) */ if (res != NULL) snmp_free_pdu (res); res = NULL; if (status == 0) csnmp_dispatch_table (host, data, instance_list, value_table); /* Free all allocated variables here */ while (instance_list != NULL) { instance_list_ptr = instance_list->next; sfree (instance_list); instance_list = instance_list_ptr; } for (i = 0; i < data->values_len; i++) { csnmp_table_values_t *tmp; while (value_table[i] != NULL) { tmp = value_table[i]->next; sfree (value_table[i]); value_table[i] = tmp; } } sfree (value_table); sfree (oid_list); return (0); } /* int csnmp_read_table */
void *poller(void *thread_args) { worker_t *worker = (worker_t *) thread_args; crew_t *crew = worker->crew; target_t *entry = NULL; void *sessp = NULL; struct snmp_session session; struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; struct variable_list *vars = NULL; unsigned long long result = 0; unsigned long long last_value = 0; unsigned long long insert_val = 0; int status = 0, bits = 0, init = 0; char query[BUFSIZE]; char storedoid[BUFSIZE]; char result_string[BUFSIZE]; if (set.verbose >= HIGH) printf("Thread [%d] starting.\n", worker->index); if (MYSQL_VERSION_ID > 40000) mysql_thread_init(); else my_thread_init(); while (1) { if (set.verbose >= DEVELOP) printf("Thread [%d] locking (wait on work)\n", worker->index); PT_MUTEX_LOCK(&crew->mutex); while (current == NULL) { PT_COND_WAIT(&crew->go, &crew->mutex); } if (set.verbose >= DEVELOP) printf("Thread [%d] done waiting, received go (work cnt: %d)\n", worker->index, crew->work_count); if (current != NULL) { if (set.verbose >= HIGH) printf("Thread [%d] processing %s %s (%d work units remain in queue)\n", worker->index, current->host, current->objoid, crew->work_count); snmp_sess_init(&session); if (set.snmp_ver == 2) session.version = SNMP_VERSION_2c; else session.version = SNMP_VERSION_1; session.peername = current->host; session.remote_port = set.snmp_port; session.community = current->community; session.community_len = strlen(session.community); sessp = snmp_sess_open(&session); anOID_len = MAX_OID_LEN; pdu = snmp_pdu_create(SNMP_MSG_GET); read_objid(current->objoid, anOID, &anOID_len); entry = current; last_value = current->last_value; init = current->init; insert_val = 0; bits = current->bits; strncpy(storedoid, current->objoid, sizeof(storedoid)); current = getNext(); } if (set.verbose >= DEVELOP) printf("Thread [%d] unlocking (done grabbing current)\n", worker->index); PT_MUTEX_UNLOCK(&crew->mutex); snmp_add_null_var(pdu, anOID, anOID_len); if (sessp != NULL) status = snmp_sess_synch_response(sessp, pdu, &response); else status = STAT_DESCRIP_ERROR; /* Collect response and process stats */ PT_MUTEX_LOCK(&stats.mutex); if (status == STAT_DESCRIP_ERROR) { stats.errors++; printf("*** SNMP Error: (%s) Bad descriptor.\n", session.peername); } else if (status == STAT_TIMEOUT) { stats.no_resp++; printf("*** SNMP No response: (%s@%s).\n", session.peername, storedoid); } else if (status != STAT_SUCCESS) { stats.errors++; printf("*** SNMP Error: (%s@%s) Unsuccessuful (%d).\n", session.peername, storedoid, status); } else if (status == STAT_SUCCESS && response->errstat != SNMP_ERR_NOERROR) { stats.errors++; printf("*** SNMP Error: (%s@%s) %s\n", session.peername, storedoid, snmp_errstring(response->errstat)); } else if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { stats.polls++; } PT_MUTEX_UNLOCK(&stats.mutex); /* Liftoff, successful poll, process it */ if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; #ifdef OLD_UCD_SNMP sprint_value(result_string, anOID, anOID_len, vars); #else snprint_value(result_string, BUFSIZE, anOID, anOID_len, vars); #endif switch (vars->type) { /* * Switch over vars->type and modify/assign result accordingly. */ case ASN_COUNTER64: if (set.verbose >= DEBUG) printf("64-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = vars->val.counter64->high; result = result << 32; result = result + vars->val.counter64->low; break; case ASN_COUNTER: if (set.verbose >= DEBUG) printf("32-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_INTEGER: if (set.verbose >= DEBUG) printf("Integer result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_GAUGE: if (set.verbose >= DEBUG) printf("32-bit gauge: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_TIMETICKS: if (set.verbose >= DEBUG) printf("Timeticks result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_OPAQUE: if (set.verbose >= DEBUG) printf("Opaque result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; default: if (set.verbose >= DEBUG) printf("Unknown result type: (%s@%s) %s\n", session.peername, storedoid, result_string); } /* Gauge Type */ if (bits == 0) { if (result != last_value) { insert_val = result; if (set.verbose >= HIGH) printf("Thread [%d]: Gauge change from %lld to %lld\n", worker->index, last_value, insert_val); } else { if (set.withzeros) insert_val = result; if (set.verbose >= HIGH) printf("Thread [%d]: Gauge steady at %lld\n", worker->index, insert_val); } /* Counter Wrap Condition */ } else if (result < last_value) { PT_MUTEX_LOCK(&stats.mutex); stats.wraps++; PT_MUTEX_UNLOCK(&stats.mutex); if (bits == 32) insert_val = (THIRTYTWO - last_value) + result; else if (bits == 64) insert_val = (SIXTYFOUR - last_value) + result; if (set.verbose >= LOW) { printf("*** Counter Wrap (%s@%s) [poll: %llu][last: %llu][insert: %llu]\n", session.peername, storedoid, result, last_value, insert_val); } /* Not a counter wrap and this is not the first poll */ } else if ((last_value >= 0) && (init != NEW)) { insert_val = result - last_value; /* Print out SNMP result if verbose */ if (set.verbose == DEBUG) printf("Thread [%d]: (%lld-%lld) = %llu\n", worker->index, result, last_value, insert_val); if (set.verbose == HIGH) printf("Thread [%d]: %llu\n", worker->index, insert_val); /* last_value < 0, so this must be the first poll */ } else { if (set.verbose >= HIGH) printf("Thread [%d]: First Poll, Normalizing\n", worker->index); } /* Check for bogus data, either negative or unrealistic */ if (insert_val > entry->maxspeed || result < 0) { if (set.verbose >= LOW) printf("*** Out of Range (%s@%s) [insert_val: %llu] [oor: %lld]\n", session.peername, storedoid, insert_val, entry->maxspeed); insert_val = 0; PT_MUTEX_LOCK(&stats.mutex); stats.out_of_range++; PT_MUTEX_UNLOCK(&stats.mutex); } if (!(set.dboff)) { if ( (insert_val > 0) || (set.withzeros) ) { PT_MUTEX_LOCK(&crew->mutex); snprintf(query, sizeof(query), "INSERT INTO %s VALUES (%d, NOW(), %llu)", entry->table, entry->iid, insert_val); if (set.verbose >= DEBUG) printf("SQL: %s\n", query); status = mysql_query(&mysql, query); if (status) printf("*** MySQL Error: %s\n", mysql_error(&mysql)); PT_MUTEX_UNLOCK(&crew->mutex); if (!status) { PT_MUTEX_LOCK(&stats.mutex); stats.db_inserts++; PT_MUTEX_UNLOCK(&stats.mutex); } } /* insert_val > 0 or withzeros */ } /* !dboff */ } /* STAT_SUCCESS */ if (sessp != NULL) { snmp_sess_close(sessp); if (response != NULL) snmp_free_pdu(response); } if (set.verbose >= DEVELOP) printf("Thread [%d] locking (update work_count)\n", worker->index); PT_MUTEX_LOCK(&crew->mutex); crew->work_count--; /* Only if we received a positive result back do we update the last_value object */ if (status == STAT_SUCCESS) entry->last_value = result; if (init == NEW) entry->init = LIVE; if (crew->work_count <= 0) { if (set.verbose >= HIGH) printf("Queue processed. Broadcasting thread done condition.\n"); PT_COND_BROAD(&crew->done); } if (set.verbose >= DEVELOP) printf("Thread [%d] unlocking (update work_count)\n", worker->index); PT_MUTEX_UNLOCK(&crew->mutex); } /* while(1) */ }
/** * snmp_set2: Gets a single value indicated by the objectid * using snmp. * @handle: a handle to the snmp session needed to make an * snmp transaction. * @objid: string containing the OID entry. * @value: the value received from snmp will be put in this union. * * In the case of multiple values being returned, the type in 'value' will be * ASN_NULL (0x05). Nothing else in 'value' will be filled in. * Use snmp_get_all for doing gets that return multiple values. * * Return value: Returns 0 if successful, -1 if there was an error. **/ SaErrorT snmp_set2(void *sessp, oid *objid, size_t objid_len, struct snmp_value *value) { struct snmp_pdu *pdu; struct snmp_pdu *response; struct variable_list *vars; struct snmp_session *session; void *dataptr = NULL; int status = 0; SaErrorT rtncode = SA_OK; /* Default - All is OK */ /* * Create the PDU for the data for our request. */ pdu = snmp_pdu_create(SNMP_MSG_SET); switch (value->type) { case ASN_INTEGER: case ASN_UNSIGNED: case ASN_COUNTER: dataptr = &value->integer; break; case ASN_OCTET_STR: dataptr = value->string; break; default: rtncode = SA_ERR_HPI_INVALID_PARAMS; dbg("datatype %c not yet supported by snmp_set2()", value->type); break; } if (rtncode == SA_OK) { /* * Set the data to send out */ /* Old code - snmp_add_var(pdu, objid, objid_len, datatype, dataptr); */ //int retcode = snmp_add_var(pdu, objid, objid_len, datatype, dataptr); snmp_pdu_add_variable(pdu, objid, objid_len, value->type, dataptr, value->str_len); /* * Send the Request out. */ status = snmp_sess_synch_response(sessp, pdu, &response); /* * Process the response. */ if (status == STAT_SUCCESS) { vars = response->variables; if (response->errstat == SNMP_ERR_NOERROR) { /* display data */ #ifdef DEBUG fprintf(stderr, "*** snmp_set2 ******************************************\n"); if (CHECK_END(response->variables->type)) { fprint_variable(stderr, response->variables->name, response->variables->name_length, response->variables); } else fprintf(stderr, "snmp_set2(): No idea.\n"); fprintf(stderr, "********************************************************\n"); #endif if (!(CHECK_END(response->variables->type)) ) { /* This is one of the exception condition */ rtncode = SA_ERR_HPI_NOT_PRESENT; dbg("snmp exception %d \n",vars->type); } } else { dbg("snmp_set2: Error in packet, Reason: %s", snmp_errstring(response->errstat)); rtncode = errstat2hpi(response->errstat); } } else { session = snmp_sess_session(sessp); snmp_sess_perror("snmpset", session); rtncode = snmpstat2hpi(status); } /* Clean up: free the response */ if (response) snmp_free_pdu(response); } return rtncode; }
/** * snmp_get2: Gets a single value indicated by the objectid * using snmp. * @handle: a handle to the snmp session needed to make an * snmp transaction. * @objid: string containing the OID entry. * @value: the value received from snmp will be put in this union. * * In the case of multiple values being returned, the type in 'value' will be * ASN_NULL (0x05). Nothing else in 'value' will be filled in. * Use snmp_get_all for doing gets that return multiple values. * * Return value: Returns 0 if successful, <0 if there was an error. **/ SaErrorT snmp_get2(void *sessp, oid *objid, size_t objid_len, struct snmp_value *value) { struct snmp_pdu *pdu; struct snmp_pdu *response; struct snmp_session *session; struct variable_list *vars; SaErrorT returncode = SA_OK; int i; int status; /* * Create the PDU for the data for our request. */ pdu = snmp_pdu_create(SNMP_MSG_GET); snmp_add_null_var(pdu, objid, objid_len); /* * Send the Request out. */ status = snmp_sess_synch_response(sessp, pdu, &response); /* * Process the response. */ if (status == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { vars = response->variables; value->type = vars->type; if (vars->next_variable != NULL) { /* If there are more values, set return type to null. */ value->type = ASN_NULL; } else if ( !(CHECK_END(vars->type)) ) { /* This is one of the exception condition */ returncode = SA_ERR_HPI_NOT_PRESENT; dbg("snmp exception %d \n",vars->type); } else if ( (vars->type == ASN_INTEGER) || (vars->type == ASN_COUNTER) || (vars->type == ASN_UNSIGNED) ) { value->integer = *(vars->val.integer); } else { value->str_len = vars->val_len; if (value->str_len >= MAX_ASN_STR_LEN) value->str_len = MAX_ASN_STR_LEN; else value->string[value->str_len] = '\0'; memcpy(value->string, vars->val.string, value->str_len); } /* display data */ #ifdef DEBUG if (CHECK_END(vars->type)) { fprintf(stderr, "*** snmp_get2 ******************************************\n"); fprint_variable(stderr, vars->name, vars->name_length, vars); fprintf(stderr, "********************************************************\n"); } else { dbg("snmp_get2(): No idea.Unknown Type: %X", vars->type); fprint_variable(stderr, vars->name, vars->name_length, vars); } #endif } else { dbg("Error, Reason: %s", snmp_errstring(response->errstat)); fprintf(stderr, "objid: "); for(i = 0; i<objid_len; i++ ) fprintf(stderr, "%d.", (int)objid[i]); fprintf(stderr, "\n"); returncode = errstat2hpi(response->errstat); } } else { session = snmp_sess_session(sessp); snmp_sess_perror("snmpget", session); returncode = snmpstat2hpi(status); } /* Clean up: free the response */ sc_free_pdu(&response); return (returncode); }
/** * snmp_set * @ss: a handle to the snmp session needed to make an snmp transaction. * @objid: string containing the OID to set. * @value: the value to set the oid with. * * Sets a value where indicated by the objectid * using snmp. * * Returns: 0 if Success, less than 0 if Failure. **/ SaErrorT snmp_set( void *sessp, char *objid, struct snmp_value value) { struct snmp_pdu *pdu; struct snmp_pdu *response; struct snmp_session *session; oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; void *dataptr = NULL; int status = 0; SaErrorT rtncode = 0; /* * Create the PDU for the data for our request. */ pdu = snmp_pdu_create(SNMP_MSG_SET); read_objid(objid, anOID, &anOID_len); rtncode = 0; /* Default - All is OK */ switch (value.type) { case ASN_INTEGER: case ASN_UNSIGNED: case ASN_COUNTER: dataptr = &value.integer; break; case ASN_OCTET_STR: dataptr = value.string; break; default: rtncode = SA_ERR_HPI_INVALID_PARAMS; dbg("datatype %c not yet supported by snmp_set()\n", value.type); break; } if (rtncode == 0) { /* * Set the data to send out */ /* Old code - int rc = snmp_add_var(pdu, objid, objid_len, datatype, dataptr) */ /* was missing checking for rc, so there was no OID and no data was */ /* included in the package. */ /* Since snmp_add_var() converts input data to string then call */ /* snmp_pdu_add_variable(), we stick with add_variable() for efficiency */ snmp_pdu_add_variable(pdu, anOID, anOID_len, value.type, dataptr, value.str_len); /* * Send the Request out. */ status = snmp_sess_synch_response(sessp, pdu, &response); /* * Process the response. */ if (status == STAT_SUCCESS) rtncode = errstat2hpi(response->errstat); else { session = snmp_sess_session(sessp); snmp_sess_perror("snmpset", session); rtncode = snmpstat2hpi(status);; } /* Clean up: free the response */ if (response) snmp_free_pdu(response); } return rtncode; }
int Host_Info::load_oid_table_get(){ unsigned int thread_id; struct snmp_session session; map<string,OID_Value_Table>::iterator iter; int fvalue=0; struct snmp_pdu *req, *resp; void *sp; // struct snmp_session *sptr; oid name[MAX_OID_LEN]; size_t name_length=MAX_OID_LEN; oid root[MAX_OID_LEN]; size_t rootlen=MAX_OID_LEN; struct variable_list *vars; char snmp_err_str[SNMP_ERR_STR_SIZE]; char buf[512]; char *placeholder; char buf2[512]; /// string temp_string1,temp_string2; int running; int status; int i; thread_id=(unsigned int) ((uint64_t)pthread_self()); snmp_sess_init(&session); session.version = SNMP_VERSION_2c; session.peername = (char *) ip_address.c_str(); session.community = (u_char *) community.c_str(); session.community_len = strlen(community.c_str()); for (iter = oid_table.begin(); iter != oid_table.end(); iter++){ assert(0==iter->first.compare(iter->second.oid)); print_log(LOG_DEBUG,"Doing host=%s for oid %s\n",ip_address.c_str(),iter->first.c_str()); rootlen = MAX_OID_LEN; //rootlen = strlen(iter->first.c_str()); if (!read_objid(iter->first.c_str(), root, &rootlen)) { //if (!Read_objid_ts(iter->first.c_str(), root, &rootlen)) { //snmp_perror(argv[arg]); //exit(1); print_log(LOG_ERR,"Cannot parse the oid='%s' rootlen=%d oid table get?\n",iter->first.c_str(),rootlen); snmp_perror("read_objid"); return -1; } if(!(sp = snmp_sess_open(&session))){ snmp_perror("snmp_open"); print_log(LOG_WARNING,"[Thread %u] SNMP table builder, failed to open session to %s\n",thread_id,ip_address.c_str()); return -1; } //////////// req = snmp_pdu_create(SNMP_MSG_GETNEXT); snmp_add_null_var(req, root, rootlen); status = snmp_sess_synch_response(sp,req,&resp); if(status == STAT_SUCCESS && resp->errstat == SNMP_ERR_NOERROR){ char buf1[512]; char *placeholder; int j; oid tmp[MAX_OID_LEN]; char temp[MAX_OID_LEN]; char ifIndexstr[MAX_OID_LEN]; string value; uint64_t local_index; vars = resp->variables; //first = malloc(sizeof(struct Value_index_mapping)); //assert(first!=NULL); //memset(buf1,'\0',sizeof(buf1)); //memset(first->value,'\0',sizeof(first->value)); //int toosmall = snprint_value(buf1, sizeof(buf1), vars->name, vars->name_length, vars); placeholder = strstr(buf1,":"); if(placeholder != NULL) placeholder = placeholder +2; if(strstr(placeholder,"\"")){ placeholder = placeholder +1; //strncpy(first->value,placeholder,strlen(placeholder)-1); value=placeholder; value.resize(value.size()-1); }else{ //strcpy(first->value,placeholder); value=placeholder; } memcpy(tmp,vars->name,vars->name_length * sizeof(oid)); for(j=0;j<vars->name_length-rootlen;j++){ if(j>0){ i = sprintf(temp, ".%d", (int) tmp[rootlen+j]); strcat(ifIndexstr,temp); }else{ i = sprintf(ifIndexstr, "%d", (int) tmp[rootlen+j]); } } //strcpy(first->index,ifIndexstr); temp_string2=ifIndexstr; local_index=atoll(temp_string2.c_str()); assert(0==1); //this should never get here! under rev 3.1.0 initial //iter->second.indexof[value]=local_index; //iter->second.valueof[local_index]=value; //first->next = NULL; //current = first; }else{ snprintf(snmp_err_str,SNMP_ERR_STR_SIZE-1,"Failure buidling snmp_table Hostname: %s snmp_sync_response",ip_address.c_str()); snmp_perror(snmp_err_str); if(resp) snmp_free_pdu(resp); snmp_sess_close(sp); return -1; } //////////////// running=1; while(running==1) { ///////// oid tmp[MAX_OID_LEN]; req = snmp_pdu_create(SNMP_MSG_GETNEXT); snmp_add_null_var(req,vars->name,vars->name_length); if(resp) snmp_free_pdu(resp); status = snmp_sess_synch_response(sp,req,&resp); if(status == STAT_SUCCESS && resp->errstat == SNMP_ERR_NOERROR){ struct Value_index_mapping *tempIndex = NULL; char buf[512]; char *placeholder; char ifIndexstr[MAX_OID_LEN]; int j; char temp[MAX_OID_LEN]; oid tmp[MAX_OID_LEN]; string value_string; string index_string; int64_t local_index; vars = resp->variables; //tempIndex = malloc(sizeof(struct Value_index_mapping)); //why allocate a != struct? //assert(tempIndex!=NULL); //memset(buf,'\0',sizeof(buf)); //memset(tempIndex->value,'\0',sizeof(tempIndex->value)); //will add a few extra bytes later, ensure we are covered snprint_value(buf, sizeof(buf)-5, vars->name, vars->name_length, vars); //printf("Raw Value = %s\n",buf); placeholder = strstr(buf,":"); if(placeholder != NULL) placeholder = placeholder +2; if(strstr(placeholder,"\"")){ placeholder = placeholder +1; //you assert on the size of the dest, not the origin assert(strlen(placeholder)+1<STD_STRING_SIZE); //strncpy(tempIndex->value,placeholder,strlen(placeholder)); value_string=placeholder; }else{ //strncpy(tempIndex->value,placeholder,STD_STRING_SIZE-1); value_string=placeholder; value_string.resize(value_string.size()-1); } memcpy(tmp,vars->name,vars->name_length * sizeof(oid)); for(j=0;j<vars->name_length-rootlen;j++){ if(j>0){ i = sprintf(temp, ".%d",(int) tmp[rootlen+j]); strcat(ifIndexstr,temp); }else{ i = sprintf(ifIndexstr, "%d",(int) tmp[rootlen+j]); } } //strcpy(tempIndex->index,ifIndexstr); index_string=ifIndexstr; local_index=atoll(index_string.c_str()); assert(1==0); //this should never reach this under 3.1.0 //iter->second.indexof[value_string]=local_index; //iter->second.valueof[local_index]=value_string; //print_log(LOG_DEBUG,"[Thread %u] Index = %u , Value = %s\n",thread_id,local_index,value_string.c_str()); //current->next = tempIndex; //current = tempIndex; //current->next = NULL; }else{ //snmp_perror("snmp_synch_response"); //snprintf(snmp_err_str,SNMP_ERR_STR_SIZE-1,"[Thread %u] Hostname: %-15s snmp_sync_response",thread_id, hostInfo.name); snmp_perror(snmp_err_str); if(resp) snmp_free_pdu(resp); snmp_sess_close(sp); return -1; } //oid tmp[MAX_OID_LEN]; memcpy(tmp,vars->name,vars->name_length * sizeof(oid)); if(tmp[rootlen-1] != root[rootlen-1]){ if(resp) snmp_free_pdu(resp); snmp_sess_close(sp); running=0; //done? } ////////// } //end while }//end for each host }
/////////////////////////////////////////////////////////////// /// Given a host loads all the oid mappings for that host /// Uses snmp bulk get to minimize the time required for each /// mapping. int Host_Info::load_oid_table(){ unsigned int thread_id; struct snmp_session session; map<string,OID_Value_Table>::iterator iter; int fvalue=0; //// //netsnmp_session session, *ss; int numprinted = 0; int reps = 15, non_reps = 0; netsnmp_pdu *pdu, *response=NULL; netsnmp_variable_list *vars; int arg; oid name[MAX_OID_LEN]; size_t name_length; oid root[MAX_OID_LEN]; size_t rootlen; int count; int running; int status; int check; int exitval = 0; struct snmp_pdu *req, *resp; void *sp; char snmp_err_str[SNMP_ERR_STR_SIZE]; char buf[512]; char *placeholder; char buf2[512]; /// string temp_string1,temp_string2; int i; //////////// thread_id=(unsigned int)((uint64_t) pthread_self()); simple_snmp_sess_init(&session); session.retries=4; session.version = SNMP_VERSION_2c; //ARE THE NEXT TWO LINES VALID???! session.peername = (char *) ip_address.c_str(); session.community = (u_char *) community.c_str(); session.community_len = strlen(community.c_str()); for (iter = oid_table.begin(); iter != oid_table.end(); iter++){ /// assert(0==iter->first.compare(iter->second.oid)); print_log(LOG_INFO,"Doing host=%s for oid %s\n",ip_address.c_str(),iter->first.c_str()); rootlen = MAX_OID_LEN; //rootlen = strlen(iter->first.c_str()); if (!read_objid(iter->first.c_str(), root, &rootlen)) { //if (!Read_objid_ts(iter->first.c_str(), root, &rootlen)) { //snmp_perror(argv[arg]); //exit(1); print_log(LOG_ERR,"Cannot parse the oid='%s' rootlen=%d host=%s\n",iter->first.c_str(),rootlen,ip_address.c_str()); snmp_perror("read_objid"); return -1; } if(!(sp = snmp_sess_open(&session))){ snmp_perror("snmp_open"); print_log(LOG_WARNING,"[Thread %u] SNMP table builder, failed to open session to %s\n",thread_id,ip_address.c_str()); return -1; } running=1; //why memmove and not memcpy? ask the netsmpbulk writers memmove(name, root, rootlen * sizeof(oid)); name_length = rootlen; //should be a while while(running==1){ /* * create PDU for GETBULK request and add object name to request */ pdu = snmp_pdu_create(SNMP_MSG_GETBULK); pdu->non_repeaters = non_reps; pdu->max_repetitions = reps; /* fill the packet */ snmp_add_null_var(pdu, name, name_length); /* * do the request */ //status = snmp_synch_response(sp, pdu, &response); status = snmp_sess_synch_response(sp,pdu,&response); switch (status){ case STAT_SUCCESS: if (response->errstat == SNMP_ERR_NOERROR) { //Yay success! ////////////// for (vars = response->variables; vars; vars = vars->next_variable) { if ((vars->name_length < rootlen) || (memcmp(root, vars->name, rootlen * sizeof(oid)) != 0)) { /* * not part of this subtree */ running = 0; continue; } numprinted++; //print_log(LOG_DEBUG,"num_printed=%d\n",numprinted); //print_variable(vars->name, vars->name_length, vars); if ((vars->type != SNMP_ENDOFMIBVIEW) && (vars->type != SNMP_NOSUCHOBJECT) && (vars->type != SNMP_NOSUCHINSTANCE)) { /* * not an exception value */ /* if (check && snmp_oid_compare(name, name_length, vars->name, vars->name_length) >= 0) { fprintf(stderr, "Error: OID not increasing: "); fprint_objid(stderr, name, name_length); fprintf(stderr, " >= "); fprint_objid(stderr, vars->name, vars->name_length); fprintf(stderr, "\n"); running = 0; exitval = 1; } */ snmp_err_str[0]=0; snprint_objid(snmp_err_str,SNMP_ERR_STR_SIZE-1,vars->name,vars->name_length); snprint_value(buf, sizeof(buf)-5, vars->name, vars->name_length, vars); //print_log(LOG_DEBUG,"[Thread %u] '%s'='%s'\n",thread_id,snmp_err_str,buf); temp_string1=snmp_err_str; size_t found; found=temp_string1.find_last_of("."); temp_string2=temp_string1.substr(found+1); string search_string; found=iter->first.find_last_not_of(".0123456789"); if(found==iter->first.npos){ //not found the search string is the whole thing! search_string=iter->first; } else{ search_string=iter->first.substr(found); } search_string=iter->first.substr((iter->first.length()*2)/3); string suffix_str; //iterate over the data. found=temp_string1.find(iter->first); found=temp_string1.find(search_string); print_log(LOG_DEBUG,"[Thread %u] [host %s] found=%u first=%s temp_string1=%s search_str=%s\n" , thread_id,ip_address.c_str(), found,iter->first.c_str(),temp_string1.c_str(),search_string.c_str()); if(temp_string1.npos!=found){ //print_log(LOG_INFO,"[Thread %u] [host %s] found!\n",thread_id,ip_address.c_str()); //suffix_str=temp_string1.substr(found+iter->first.length()+1); suffix_str=temp_string1.substr(found+search_string.length()+1); //print_log(LOG_INFO,"[Thread %u] found=%u first=%s temp_string1=%s\n" , thread_id,found,iter->first.c_str(),temp_string1.c_str()); print_log(LOG_DEBUG,"[Thread %u] [host %s] found =%s!\n",thread_id,ip_address.c_str(),suffix_str.c_str()); } else{ print_log(LOG_DEBUG,"[Thread %u] [host %s] NOT found!\n",thread_id,ip_address.c_str()); found=temp_string1.find_last_of("."); suffix_str=temp_string1.substr(found+1); } //print_log(LOG_DEBUG,"[Thread %u] index='%s'\n",thread_id,temp_string2.c_str()); uint64_t local_index; local_index=atoll(temp_string2.c_str()); //printf("Raw Value = %s\n",buf); temp_string2=extract_value_from_raw(buf); //print_log(LOG_DEBUG,"[Thread %u] index=%lu value='%s' \n",thread_id,local_index,buf2); //iter->second.indexof[temp_string2]=local_index; //iter->second.valueof[local_index]=temp_string2; iter->second.suffix_of[temp_string2]=suffix_str; iter->second.value_of[suffix_str]=temp_string2; print_log(LOG_DEBUG,"[Thread %u] [host %s] suffix_of[%s]='%s' \n",thread_id,ip_address.c_str(),temp_string2.c_str(),suffix_str.c_str()); /* * Check if last variable, and if so, save for next request. */ if (vars->next_variable == NULL) { memmove(name, vars->name, vars->name_length * sizeof(oid)); name_length = vars->name_length; } } else { /* * an exception value, so stop */ running = 0; } } //////////////// } else{ ///Error in response, report and exit loop running=0; snprintf(snmp_err_str,SNMP_ERR_STR_SIZE-1,"[Thread %u] Hostname: %-15s snmp_sync_response",thread_id, ip_address.c_str()); snmp_perror(snmp_err_str); } break; case STAT_TIMEOUT: print_log(LOG_NOTICE,"[Thread %u] SNMP timeout(building table), host=%15s \n",thread_id, ip_address.c_str() ); running=0; break; default: //other error! print_log(LOG_ERR,"SNMP MISC error\n"); running=0; break; } if (response){ snmp_free_pdu(response); response=NULL; } if(0==iter->second.suffix_of.size()){ print_log(LOG_WARNING,"[Thread %u][host %s] no data inserted for %s\n",thread_id,ip_address.c_str(),iter->first.c_str()); //fvalue=-1; } //print_log(LOG_DEBUG,"[Thread %u] inserted %d values\n" ,thread_id,iter->second.indexof.size()); }//end while if (response){ snmp_free_pdu(response); response=NULL; } //is this the best place to clse it? snmp_sess_close(sp); }//end for return fvalue; }
void *sync_poller(void *thread_args) { // phoenix async poller; worker_t *worker = (worker_t *) thread_args; crew_t *crew = worker -> crew; // target_t *entry = NULL; target_t *_current_local = NULL; PT_MUTEX_LOCK(&crew -> mutex); PT_COND_WAIT(&crew->go, &crew->mutex); PT_MUTEX_UNLOCK(&crew -> mutex); for( ; ; ) { PT_MUTEX_LOCK(&crew -> mutex); current = _current_local = getNext(); crew -> _sent_work_count--; if (_current_local == NULL && crew->_sent_work_count <= 0) { crew -> _send_worker_count--; PT_COND_BROAD(&crew -> _sending_done); PT_COND_WAIT(&crew -> go, &crew -> mutex); // } else if (_current_local == NULL) { // PT_COND_WAIT(&crew->go, &crew->mutex); // // PT_MUTEX_UNLOCK(&crew -> mutex); // continue; // // return 0; // } else if (crew->_sent_work_count <= 0) { // PT_COND_BROAD(&crew->_sending_done); // // PT_MUTEX_UNLOCK(&crew -> mutex); // continue; // // return 0; PT_MUTEX_UNLOCK(&crew -> mutex); continue; } PT_MUTEX_UNLOCK(&crew -> mutex); // PT_MUTEX_LOCK(&crew->mutex); // current = getNext(); // if (status == STAT_SUCCESS) entry->last_value = result; // if (init == NEW) entry->init = LIVE; // signal for our control thread; // but should also check for number of threads completed; // PT_MUTEX_UNLOCK(&crew->mutex); // while (current == NULL) { // PT_COND_WAIT(&crew -> go, &crew -> mutex); // _current_local = NULL; // } // // if (current != NULL) { // _current_local = current; // // printf("[ info] thread [%d] work_count index: %d\n", worker->index, crew -> _send_work_count); // } // make a copy of current and then unlock; // preparing snmp session; // we got what we need from current entry // moving to next entry for other wating threads; printf( "[ info] thread [%d] processing -> host: %s, oid: %s\n", worker -> index, _current_local -> host, _current_local -> objoid ); // making a snmp session ... // struct session *_host_ss = stuepd you are, this is a ptr! sohuld be initialized 1st :- ; struct session *_host_ss = calloc(1, sizeof(struct session)); // stuepd you are, this is a ptr! sohuld be initialized 1st :- ; // struct host *hp; /* startup all hosts */ // for (hs = sessions, hp = hosts; hp->name; hs++, hp++) { struct snmp_session _sess; struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; snmp_sess_init(&_sess); /* initialize session */ _sess.version = SNMP_VERSION_2c; _sess.peername = strdup(_current_local-> host); _sess.community = strdup(_current_local -> community); _sess.community_len = strlen(_sess.community); // /* default callback */ // _sess.callback = asynch_response; // _sess.callback_magic = _host_ss; // if (!(_host_ss -> _sess = snmp_sess_open(&_sess))) { //, snmp_api_errstring(snmp_errno) printf("[error] %s!\n", snmp_api_errstring(snmp_errno)); // exit(-1); // snmp_perror(snmp_errno); continue; } // printf("[ info] thread [%d] &sess: %llu, _host_ss -> _sess: %llu\n", worker->index, // &sess, _host_ss -> _sess); // struct snmp_session *_ss_ptr = snmp_sess_session(_host_ss -> _sess); _host_ss -> _oid_name = strdup(_current_local -> objoid); // also translate this in to snmp format; _host_ss -> _oid_len = sizeof(_host_ss -> _oid) / sizeof(_host_ss -> _oid[0]); if (!read_objid(_host_ss -> _oid_name, _host_ss -> _oid, &_host_ss -> _oid_len)) { snmp_perror("read_objid"); exit(1); } pdu = snmp_pdu_create(SNMP_MSG_GET); /* send the first GET */ snmp_add_null_var(pdu, _host_ss -> _oid, _host_ss -> _oid_len); int _status = snmp_sess_synch_response(_host_ss -> _sess, pdu, &response); // int print_result (int status, struct snmp_session *sp, struct snmp_pdu *pdu) print_result(_status, &_sess, response); // analyzing the result; // and making it look like correct one (limits and correctness check); // if out of range for example we have the following stats update; // PT_MUTEX_LOCK(&stats.mutex); // stats.out_of_range++; // PT_MUTEX_UNLOCK(&stats.mutex); snmp_sess_close(_host_ss -> _sess); /* Collect response and process stats */ PT_MUTEX_LOCK(&stats.mutex); // when we have a snmp result, updating a starts counters; PT_MUTEX_UNLOCK(&stats.mutex); // decreasing work counter; } // for (;;) }
static int csnmp_read_table (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; struct snmp_pdu *res; struct variable_list *vb; const data_set_t *ds; oid_t *oid_list; uint32_t oid_list_len; int status; int i; /* `value_list_head' and `value_list_tail' implement a linked list for each * value. `instance_list_head' and `instance_list_tail' implement a linked list of * instance names. This is used to jump gaps in the table. */ csnmp_list_instances_t *instance_list_head; csnmp_list_instances_t *instance_list_tail; csnmp_table_values_t **value_list_head; csnmp_table_values_t **value_list_tail; DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL"); return (-1); } ds = plugin_get_ds (data->type); if (!ds) { ERROR ("snmp plugin: DataSet `%s' not defined.", data->type); return (-1); } if (ds->ds_num != data->values_len) { ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i", data->type, ds->ds_num, data->values_len); return (-1); } /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ oid_list_len = data->values_len + 1; oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len)); if (oid_list == NULL) { ERROR ("snmp plugin: csnmp_read_table: malloc failed."); return (-1); } memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); if (data->instance.oid.oid_len > 0) memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t)); else oid_list_len--; /* We're going to construct n linked lists, one for each "value". * value_list_head will contain pointers to the heads of these linked lists, * value_list_tail will contain pointers to the tail of the lists. */ value_list_head = calloc (data->values_len, sizeof (*value_list_head)); value_list_tail = calloc (data->values_len, sizeof (*value_list_tail)); if ((value_list_head == NULL) || (value_list_tail == NULL)) { ERROR ("snmp plugin: csnmp_read_table: calloc failed."); sfree (oid_list); sfree (value_list_head); sfree (value_list_tail); return (-1); } instance_list_head = NULL; instance_list_tail = NULL; status = 0; while (status == 0) { req = snmp_pdu_create (SNMP_MSG_GETNEXT); if (req == NULL) { ERROR ("snmp plugin: snmp_pdu_create failed."); status = -1; break; } for (i = 0; (uint32_t) i < oid_list_len; i++) snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len); res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); c_complain (LOG_ERR, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response failed: %s", host->name, (errstr == NULL) ? "Unknown problem" : errstr); if (res != NULL) snmp_free_pdu (res); res = NULL; sfree (errstr); csnmp_host_close_session (host); status = -1; break; } status = 0; assert (res != NULL); c_release (LOG_INFO, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response successful.", host->name); vb = res->variables; if (vb == NULL) { status = -1; break; } /* Check if all values (and possibly the instance) have left their * subtree */ if (csnmp_check_res_left_subtree (host, data, res) != 0) { status = 0; break; } /* Copy the OID of the value used as instance to oid_list, if an instance * is configured. */ if (data->instance.oid.oid_len > 0) { /* Allocate a new `csnmp_list_instances_t', insert the instance name and * add it to the list */ if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail, res, host, data) != 0) { ERROR ("snmp plugin: csnmp_instance_list_add failed."); status = -1; break; } /* The instance OID is added to the list of OIDs to GET from the * snmp agent last, so set vb on the last variable returned and copy * that OID. */ for (vb = res->variables; (vb != NULL) && (vb->next_variable != NULL); vb = vb->next_variable) /* do nothing */; assert (vb != NULL); /* Copy the OID of the instance value to oid_list[data->values_len]. * "oid_list" is used for the next GETNEXT request. */ memcpy (oid_list[data->values_len].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[data->values_len].oid_len = vb->name_length; } /* Iterate over all the (non-instance) values returned by the agent. The * (i < value_len) check will make sure we're not handling the instance OID * twice. */ for (vb = res->variables, i = 0; (vb != NULL) && (i < data->values_len); vb = vb->next_variable, i++) { csnmp_table_values_t *vt; oid_t vb_name; oid_t suffix; csnmp_oid_init (&vb_name, vb->name, vb->name_length); /* Calculate the current suffix. This is later used to check that the * suffix is increasing. This also checks if we left the subtree */ status = csnmp_oid_suffix (&suffix, &vb_name, data->values + i); if (status != 0) { DEBUG ("snmp plugin: host = %s; data = %s; Value %i failed. " "It probably left its subtree.", host->name, data->name, i); continue; } /* Make sure the OIDs returned by the agent are increasing. Otherwise our * table matching algorithm will get confused. */ if ((value_list_tail[i] != NULL) && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0)) { DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " "Suffix is not increasing.", host->name, data->name, i); continue; } vt = malloc (sizeof (*vt)); if (vt == NULL) { ERROR ("snmp plugin: malloc failed."); status = -1; break; } memset (vt, 0, sizeof (*vt)); vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift, host->name, data->name); memcpy (&vt->suffix, &suffix, sizeof (vt->suffix)); vt->next = NULL; if (value_list_tail[i] == NULL) value_list_head[i] = vt; else value_list_tail[i]->next = vt; value_list_tail[i] = vt; /* Copy OID to oid_list[i + 1] */ memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[i].oid_len = vb->name_length; } /* for (i = data->values_len) */ if (res != NULL) snmp_free_pdu (res); res = NULL; } /* while (status == 0) */ if (res != NULL) snmp_free_pdu (res); res = NULL; if (status == 0) csnmp_dispatch_table (host, data, instance_list_head, value_list_head); /* Free all allocated variables here */ while (instance_list_head != NULL) { csnmp_list_instances_t *next = instance_list_head->next; sfree (instance_list_head); instance_list_head = next; } for (i = 0; i < data->values_len; i++) { while (value_list_head[i] != NULL) { csnmp_table_values_t *next = value_list_head[i]->next; sfree (value_list_head[i]); value_list_head[i] = next; } } sfree (value_list_head); sfree (value_list_tail); sfree (oid_list); return (0); } /* int csnmp_read_table */