Exemple #1
0
/**
 * 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 {
Exemple #5
0
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);

}
Exemple #6
0
// 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;
}
Exemple #7
0
/**
 * 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);
}
Exemple #8
0
/*! \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);
	}
}
Exemple #9
0
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(&current_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 */
}
Exemple #10
0
/*! \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);
	}
}
Exemple #11
0
/*! \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;
}
Exemple #12
0
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 */
Exemple #13
0
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 */
Exemple #14
0
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 */
Exemple #15
0
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) */
}
Exemple #16
0
/**
 * 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;

}
Exemple #17
0
/**
 * 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);
}
Exemple #18
0
/**
 * 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;
}
Exemple #19
0
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

}
Exemple #20
0
///////////////////////////////////////////////////////////////
/// 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;
}
Exemple #21
0
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 (;;)

}
Exemple #22
0
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 */