/**
 * load initial data
 *
 * TODO:350:M: Implement dessertMeshifTable data load
 * This function will also be called by the cache helper to load
 * the container again (after the container free function has been
 * called to free the previous contents).
 *
 * @param container container to which items should be inserted
 *
 * @retval MFD_SUCCESS              : success.
 * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source
 * @retval MFD_ERROR                : other error.
 *
 *  This function is called to load the index(es) (and data, optionally)
 *  for the every row in the data set.
 *
 * @remark
 *  While loading the data, the only important thing is the indexes.
 *  If access to your data is cheap/fast (e.g. you have a pointer to a
 *  structure in memory), it would make sense to update the data here.
 *  If, however, the accessing the data invovles more work (e.g. parsing
 *  some other existing data, or peforming calculations to derive the data),
 *  then you can limit yourself to setting the indexes and saving any
 *  information you will need later. Then use the saved information in
 *  dessertMeshifTable_row_prep() for populating data.
 *
 * @note
 *  If you need consistency between rows (like you want statistics
 *  for each row to be from the same time frame), you should set all
 *  data here.
 *
 */
int
dessertMeshifTable_container_load(netsnmp_container * container)
{
    dessertMeshifTable_rowreq_ctx *rowreq_ctx;
    dessert_meshif_t *meshif;
    size_t          count = 0;

    char inPkts[I64CHARSZ+1];
    char outPkts[I64CHARSZ+1];
    char inOctets[I64CHARSZ+1];
    char outOctets[I64CHARSZ+1];

    /*
     * temporary storage for index values
     */
    /*
     * meshifIndex(1)///()//L/a/w/e/r/d/h
     */
    long meshifIndex = -1;

    dessert_debug("dessertMeshifTable_container_load called");
    DEBUGMSGTL(("verbose:dessertMeshifTable:dessertMeshifTable_container_load", "called\n"));



	/*
	 * TODO:351:M: |-> Load/update data in the dessertMeshifTable container.
	 * loop over your dessertMeshifTable data, allocate a rowreq context,
	 * set the index(es) [and data, optionally] and insert into
	 * the container.
	 */
    pthread_rwlock_rdlock(&dessert_cfglock);
	DL_FOREACH(dessert_meshiflist_get(), meshif){

		meshifIndex = ++count;

		/*
		 * TODO:352:M: |   |-> set indexes in new dessertMeshifTable rowreq context.
		 * data context will be set from the param (unless NULL,
		 *      in which case a new data context will be allocated)
		 */
		rowreq_ctx = dessertMeshifTable_allocate_rowreq_ctx(NULL);
		if (NULL == rowreq_ctx) {
			snmp_log(LOG_ERR, "memory allocation failed\n");
			pthread_rwlock_unlock(&dessert_cfglock);
			return MFD_RESOURCE_UNAVAILABLE;
		}

		if (MFD_SUCCESS != dessertMeshifTable_indexes_set(rowreq_ctx,
				meshifIndex)) {
			snmp_log(LOG_ERR, "error setting index while loading "
				"dessertMeshifTable data.\n");
			dessertMeshifTable_release_rowreq_ctx(rowreq_ctx);
			continue;
		}

		/*
		 * TODO:352:r: |   |-> populate dessertMeshifTable data context.
		 * Populate data context here. (optionally, delay until row prep)
		 */

		rowreq_ctx->data.meshifName_len = strlen(meshif->if_name);
		strcpy(rowreq_ctx->data.meshifName, meshif->if_name);

		rowreq_ctx->data.meshifMacAddress_len = 6;
		memcpy(rowreq_ctx->data.meshifMacAddress, meshif->hwaddr, 6);

		pthread_mutex_lock(&(meshif->cnt_mutex));

		rowreq_ctx->data.meshifInPkts.low   = meshif->ipkts & 0xffffffff;
		rowreq_ctx->data.meshifInPkts.high  = meshif->ipkts >> 32;

		rowreq_ctx->data.meshifOutPkts.low  = meshif->opkts & 0xffffffff;
		rowreq_ctx->data.meshifOutPkts.high = meshif->opkts >> 32;

		rowreq_ctx->data.meshifInOctets.low  = meshif->ibytes & 0xffffffff;
		rowreq_ctx->data.meshifInOctets.high = meshif->ibytes >> 32;

		rowreq_ctx->data.meshifOutOctets.low = meshif->obytes & 0xffffffff;
		rowreq_ctx->data.meshifOutOctets.high = meshif->obytes >> 32;


		printU64(inPkts, &rowreq_ctx->data.meshifInPkts);
		printU64(outPkts, &rowreq_ctx->data.meshifOutPkts);
		printU64(inOctets, &rowreq_ctx->data.meshifInOctets);
		printU64(outOctets, &rowreq_ctx->data.meshifOutOctets);


		dessert_debug("inPkts    [%s] [%u]", inPkts, meshif->ipkts);
		dessert_debug("outPkts   [%s] [%u]", outPkts, meshif->opkts);
		dessert_debug("inOctets  [%s] [%u]", inOctets, meshif->ibytes);
		dessert_debug("outOctets [%s] [%u]", outOctets,meshif->obytes);


		pthread_mutex_unlock(&(meshif->cnt_mutex));

		/*
		 * insert into table container
		 */
		CONTAINER_INSERT(container, rowreq_ctx);
	}
Exemplo n.º 2
0
/**
 * Get snmp value to the structure my_poid_result->
 * Author : lining 15810423651 [email protected] 
 * @param netsnmp_variable_list *vars  : the return pdu variable value.
 * @param my_oid_result : the structure my_poid_result->
 * @return void.
 */
void get_oid_value(netsnmp_variable_list *vars, my_oid_result **oid_result) {
	
	unsigned int count = 0;
	
	(*oid_result)->oid_name_length = vars->name_length;	
	
	for(count=0; count < vars->name_length; count++) {
		(*oid_result)->oid_name[count]	= *(vars->name+count);
	}
	(*oid_result)->val_len = vars->val_len;
	
	(*oid_result)->type = vars->type;

	if(vars->type == SNMP_NOSUCHOBJECT) {
		return;
	}
	
	if(vars->type == SNMP_NOSUCHINSTANCE) {
		return;
	}
	
	if(vars->type == SNMP_ENDOFMIBVIEW) {
		return;
	}
	
	if (vars->type == ASN_OCTET_STR) { 

		int hex = 0;
		int x;
		u_char * cp;
		int allow_realloc = 1;
		u_char *buf = NULL;
		size_t buf_len = 256, out_len = 0;

		for (cp = vars->val.string, x = 0; x < (int)vars->val_len; x++, cp++) {
			if (!isprint(*cp) && !isspace(*cp)) {
				hex = 1;
			}
		}
		
		if(!hex) {
			for(count=0; count < vars->val_len; count++) {
				(*oid_result)->val.string[count] = vars->val.string[count];
			}
			return;
			
		} else {
			buf = (u_char *) calloc(buf_len, 1);
			sprint_realloc_hexstring(&buf, &buf_len, &out_len, allow_realloc, vars->val.string, vars->val_len);
			
			for(count=0; count < strlen(buf); count++) {
				(*oid_result)->val.string[count] = buf[count];
			}
			(*oid_result)->val.string[strlen(buf)] = 0;
			
			free(buf);
			return;
		}

	}

	if (vars->type == ASN_BIT_STR) {
		sprintf((*oid_result)->val.bitstring, "%s" ,vars->val.bitstring);
		return;
	}
	
	if (vars->type == ASN_OPAQUE) {
		return;
	}
	
	if (vars->type == ASN_INTEGER) {
		(*oid_result)->val.integer = *vars->val.integer;
		(*oid_result)->val.integer = (*oid_result)->val.integer & 0x00000000ffffffff;
		return;
	}
	
	if (vars->type == ASN_UINTEGER) {
		(*oid_result)->val.integer = *vars->val.integer;
		(*oid_result)->val.integer = (*oid_result)->val.integer & 0x00000000ffffffff;
		return;
	}
	
	if (vars->type == ASN_OBJECT_ID) {
		(*oid_result)->objid_length = vars->val_len/sizeof(oid);
		for(count=0; count < (*oid_result)->objid_length; count++) {
			(*oid_result)->val.objid[count] = vars->val.objid[count];
		}
		return;
	}
	
	if (vars->type == ASN_TIMETICKS) {
		(*oid_result)->val.integer = *(u_long *)vars->val.integer;
		return;
	}
	
	if (vars->type == ASN_IPADDRESS) {
		(*oid_result)->val.string[0] = vars->val.string[0];
		(*oid_result)->val.string[1] = vars->val.string[1];
		(*oid_result)->val.string[2] = vars->val.string[2];
		(*oid_result)->val.string[3] = vars->val.string[3];
		return;
	}
	
	if (vars->type == ASN_OPAQUE_I64) {
		printI64((*oid_result)->val.string, vars->val.counter64);
		return;
	}
	
	if (vars->type == ASN_OPAQUE_COUNTER64 || vars->type == ASN_OPAQUE_U64 || vars->type == ASN_COUNTER64) {
		printU64((*oid_result)->val.string, vars->val.counter64);
		return;
	}

	if (vars->type == ASN_COUNTER) {
		(*oid_result)->val.integer = *vars->val.integer;
		return;
	}
	
	if (vars->type == ASN_GAUGE) {
		(*oid_result)->val.integer = *vars->val.integer;
		return;
	}
	
	if (vars->type == ASN_OPAQUE_FLOAT) {
		(*oid_result)->val.floatVal = *vars->val.floatVal;
		return;
	}
	
	if (vars->type == ASN_OPAQUE_DOUBLE) {
		(*oid_result)->val.doubleVal = *vars->val.doubleVal;
		return;
	}
	
	if (vars->type == ASN_NULL) {
		return;
	}
	
	return;
}
Exemplo n.º 3
0
int
main(int argc, char *argv[])
{
    netsnmp_session session, *ss;
    netsnmp_pdu    *pdu, *response;
    netsnmp_variable_list *vars;
    int             arg;
    char           *gateway;

    int             count;
    struct varInfo *vip;
    u_int           value = 0;
    struct counter64 c64value;
    float           printvalue;
    time_t          last_time = 0;
    time_t          this_time;
    time_t          delta_time;
    int             sum;        /* what the heck is this for, its never used? */
    char            filename[128] = { 0 };
    struct timeval  tv;
    struct tm       tm;
    char            timestring[64] = { 0 }, valueStr[64] = {
    0}, maxStr[64] = {
    0};
    char            outstr[256] = { 0 }, peakStr[64] = {
    0};
    int             status;
    int             begin, end, last_end;
    int             print = 1;
    int             exit_code = 1;

    SOCK_STARTUP;

    switch (arg = snmp_parse_args(argc, argv, &session, "C:", &optProc)) {
    case NETSNMP_PARSE_ARGS_ERROR:
        goto out;
    case NETSNMP_PARSE_ARGS_SUCCESS_EXIT:
        exit_code = 0;
        goto out;
    case NETSNMP_PARSE_ARGS_ERROR_USAGE:
        usage();
        goto out;
    default:
        break;
    }

    gateway = session.peername;

    for (; optind < argc; optind++) {
	if (current_name >= MAX_ARGS) {
	    fprintf(stderr, "%s: Too many variables specified (max %d)\n",
	    	argv[optind], MAX_ARGS);
	    goto out;
	}
        varinfo[current_name++].name = argv[optind];
    }

    if (current_name == 0) {
        usage();
        goto out;
    }

    if (dosum) {
	if (current_name >= MAX_ARGS) {
	    fprintf(stderr, "Too many variables specified (max %d)\n",
	    	MAX_ARGS);
	    goto out;
	}
        varinfo[current_name++].name = NULL;
    }

    /*
     * open an SNMP session 
     */
    ss = snmp_open(&session);
    if (ss == NULL) {
        /*
         * diagnose snmp_open errors with the input netsnmp_session pointer 
         */
        snmp_sess_perror("snmpdelta", &session);
        goto out;
    }

    if (tableForm && timestamp) {
        printf("%s", gateway);
    }
    for (count = 0; count < current_name; count++) {
        vip = varinfo + count;
        if (vip->name) {
            vip->oidlen = MAX_OID_LEN;
            vip->info_oid = (oid *) malloc(sizeof(oid) * vip->oidlen);
            if (snmp_parse_oid(vip->name, vip->info_oid, &vip->oidlen) ==
                NULL) {
                snmp_perror(vip->name);
                goto close_session;
            }
            sprint_descriptor(vip->descriptor, vip);
            if (tableForm)
                printf("\t%s", vip->descriptor);
        } else {
            vip->oidlen = 0;
            strlcpy(vip->descriptor, SumFile, sizeof(vip->descriptor));
        }
        vip->value = 0;
        zeroU64(&vip->c64value);
        vip->time = 0;
        vip->max = 0;
        if (peaks) {
            vip->peak_count = -1;
            vip->peak = 0;
            vip->peak_average = 0;
        }
    }

    wait_for_period(period);

    end = current_name;
    sum = 0;
    while (1) {
        pdu = snmp_pdu_create(SNMP_MSG_GET);

        if (deltat)
            snmp_add_null_var(pdu, sysUpTimeOid, sysUpTimeLen);

        if (end == current_name)
            count = 0;
        else
            count = end;
        begin = count;
        for (; count < current_name
             && count < begin + varbindsPerPacket - deltat; count++) {
            if (varinfo[count].oidlen)
                snmp_add_null_var(pdu, varinfo[count].info_oid,
                                  varinfo[count].oidlen);
        }
        last_end = end;
        end = count;

      retry:
        status = snmp_synch_response(ss, pdu, &response);
        if (status == STAT_SUCCESS) {
            if (response->errstat == SNMP_ERR_NOERROR) {
                if (timestamp) {
                    gettimeofday(&tv, (struct timezone *) 0);
                    memcpy(&tm, localtime((time_t *) & tv.tv_sec),
                           sizeof(tm));
                    if (((period % 60)
                         && (!peaks || ((period * peaks) % 60)))
                        || keepSeconds)
                        sprintf(timestring, " [%02d:%02d:%02d %d/%d]",
                                tm.tm_hour, tm.tm_min, tm.tm_sec,
                                tm.tm_mon + 1, tm.tm_mday);
                    else
                        sprintf(timestring, " [%02d:%02d %d/%d]",
                                tm.tm_hour, tm.tm_min,
                                tm.tm_mon + 1, tm.tm_mday);
                }

                vars = response->variables;
                if (deltat) {
                    if (!vars || !vars->val.integer) {
                        fprintf(stderr, "Missing variable in reply\n");
                        continue;
                    } else {
                        this_time = *(vars->val.integer);
                    }
                    vars = vars->next_variable;
                } else {
                    this_time = 1;
                }

                for (count = begin; count < end; count++) {
                    vip = varinfo + count;

                    if (vip->oidlen) {
                        if (!vars || !vars->val.integer) {
                            fprintf(stderr, "Missing variable in reply\n");
                            break;
                        }
                        vip->type = vars->type;
                        if (vars->type == ASN_COUNTER64) {
                            u64Subtract(vars->val.counter64,
                                        &vip->c64value, &c64value);
                            memcpy(&vip->c64value, vars->val.counter64,
                                   sizeof(struct counter64));
                        } else {
                            value = *(vars->val.integer) - vip->value;
                            vip->value = *(vars->val.integer);
                        }
                        vars = vars->next_variable;
                    } else {
                        value = sum;
                        sum = 0;
                    }
                    delta_time = this_time - vip->time;
                    if (delta_time <= 0)
                        delta_time = 100;
                    last_time = vip->time;
                    vip->time = this_time;
                    if (last_time == 0)
                        continue;

                    if (vip->oidlen && vip->type != ASN_COUNTER64) {
                        sum += value;
                    }

                    if (tableForm) {
                        if (count == begin) {
                            sprintf(outstr, "%s", timestring + 1);
                        } else {
                            outstr[0] = '\0';
                        }
                    } else {
                        sprintf(outstr, "%s %s", timestring,
                                vip->descriptor);
                    }

                    if (deltat || tableForm) {
                        if (vip->type == ASN_COUNTER64) {
                            fprintf(stderr,
                                    "time delta and table form not supported for counter64s\n");
                            goto close_session;
                        } else {
                            printvalue =
                                ((float) value * 100) / delta_time;
                            if (tableForm)
                                sprintf(valueStr, "\t%.2f", printvalue);
                            else
                                sprintf(valueStr, " /sec: %.2f",
                                        printvalue);
                        }
                    } else {
                        printvalue = (float) value;
                        sprintf(valueStr, " /%d sec: ", period);
                        if (vip->type == ASN_COUNTER64)
                            printU64(valueStr + strlen(valueStr),
                                     &c64value);
                        else
                            sprintf(valueStr + strlen(valueStr), "%u",
                                    value);
                    }

                    if (!peaks) {
                        strcat(outstr, valueStr);
                    } else {
                        print = 0;
                        if (vip->peak_count == -1) {
                            if (wait_for_peak_start(period, peaks) == 0)
                                vip->peak_count = 0;
                        } else {
                            vip->peak_average += printvalue;
                            if (vip->peak < printvalue)
                                vip->peak = printvalue;
                            if (++vip->peak_count == peaks) {
                                if (deltat)
                                    sprintf(peakStr,
                                            " /sec: %.2f	(%d sec Peak: %.2f)",
                                            vip->peak_average /
                                            vip->peak_count, period,
                                            vip->peak);
                                else
                                    sprintf(peakStr,
                                            " /%d sec: %.0f	(%d sec Peak: %.0f)",
                                            period,
                                            vip->peak_average /
                                            vip->peak_count, period,
                                            vip->peak);
                                vip->peak_average = 0;
                                vip->peak = 0;
                                vip->peak_count = 0;
                                print = 1;
                                strcat(outstr, peakStr);
                            }
                        }
                    }

                    if (printmax) {
                        if (printvalue > vip->max) {
                            vip->max = printvalue;
                        }
                        if (deltat)
                            sprintf(maxStr, "	(Max: %.2f)", vip->max);
                        else
                            sprintf(maxStr, "	(Max: %.0f)", vip->max);
                        strcat(outstr, maxStr);
                    }

                    if (print) {
                        if (fileout) {
                            sprintf(filename, "%s-%s", gateway,
                                    vip->descriptor);
                            print_log(filename, outstr + 1);
                        } else {
                            if (tableForm)
                                printf("%s", outstr);
                            else
                                printf("%s\n", outstr + 1);
                            fflush(stdout);
                        }
                    }
                }
                if (end == last_end && tableForm)
                    printf("\n");
            } else {
                if (response->errstat == SNMP_ERR_TOOBIG) {
                    if (response->errindex <= varbindsPerPacket
                        && response->errindex > 0) {
                        varbindsPerPacket = response->errindex - 1;
                    } else {
                        if (varbindsPerPacket > 30)
                            varbindsPerPacket -= 5;
                        else
                            varbindsPerPacket--;
                    }
                    if (varbindsPerPacket <= 0) {
                        exit_code = 5;
                        break;
                    }
                    end = last_end;
                    continue;
                } else if (response->errindex != 0) {
                    fprintf(stderr, "Failed object: ");
                    for (count = 1, vars = response->variables;
                         vars && count != response->errindex;
                         vars = vars->next_variable, count++);
                    if (vars)
                        fprint_objid(stderr, vars->name,
                                     vars->name_length);
                    fprintf(stderr, "\n");
                    /*
                     * Don't exit when OIDs from file are not found on agent
                     * exit_code = 1;
                     * break;
                     */
                } else {
                    fprintf(stderr, "Error in packet: %s\n",
                            snmp_errstring(response->errstat));
                    exit_code = 1;
                    break;
                }

                /*
                 * retry if the errored variable was successfully removed 
                 */
                if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
					    NETSNMP_DS_APP_DONT_FIX_PDUS)) {
                    pdu = snmp_fix_pdu(response, SNMP_MSG_GET);
                    snmp_free_pdu(response);
                    response = NULL;
                    if (pdu != NULL)
                        goto retry;
                }
            }

        } else if (status == STAT_TIMEOUT) {
            fprintf(stderr, "Timeout: No Response from %s\n", gateway);
            response = NULL;
            exit_code = 1;
            break;
        } else {                /* status == STAT_ERROR */
            snmp_sess_perror("snmpdelta", ss);
            response = NULL;
            exit_code = 1;
            break;
        }

        if (response)
            snmp_free_pdu(response);
        if (end == current_name) {
            wait_for_period(period);
        }
    }

    exit_code = 0;

close_session:
    snmp_close(ss);

out:
    SOCK_CLEANUP;
    return (exit_code);
}
Exemplo n.º 4
0
/**
 * Get snmp value to the struct my_oid_result.
 * Author : lining 15810423651 [email protected] 
 * @param netsnmp_variable_list *vars  : the return pdu variable value.
 * @param my_oid_result : the struct my_oid_result.
 * @return void.
 */
void get_bulkwalk_oid_values(netsnmp_variable_list *vars, my_oid_result *oid_result) {
	
	unsigned int count = 0;
	
	oid_result->oid_name_length = vars->name_length;
	
	for(count=0; count < vars->name_length; count++) {
		oid_result->oid_name[count]	= *(vars->name+count);
	}
	
	oid_result->val_len = vars->val_len;
	oid_result->type = vars->type;
	
	if(vars->type == SNMP_NOSUCHOBJECT) {
		return;
	}
	
	if(vars->type == SNMP_NOSUCHINSTANCE) {
		return;
	}
	
	if(vars->type == SNMP_ENDOFMIBVIEW) {
		return;
	}
	if (vars->type == ASN_OCTET_STR) {
		for(count=0; count < vars->val_len; count++) {
			oid_result->val.string[count] = vars->val.string[count];
		}
		return;
	}
	if (vars->type == ASN_BIT_STR) {
		sprintf(oid_result->val.bitstring, "%s" ,vars->val.bitstring);
		return;
	}
	
	if (vars->type == ASN_OPAQUE) {
		return;
	}
	
	if (vars->type == ASN_INTEGER) {
		oid_result->val.integer = *vars->val.integer;
		return;
	}

	if (vars->type == ASN_UINTEGER) {
		oid_result->val.integer = *vars->val.integer;
		return;
	}
	
	if (vars->type == ASN_OBJECT_ID) {
		oid_result->objid_length = vars->val_len/sizeof(oid);
		for(count=0; count < oid_result->objid_length; count++) {
			oid_result->val.objid[count] = vars->val.objid[count];
		}
		return;
	}

	if (vars->type == ASN_TIMETICKS) {
		oid_result->val.integer = *(u_long *)vars->val.integer;
		return;
	}
	
	if (vars->type == ASN_IPADDRESS) {
		oid_result->val.string[0] = vars->val.string[0];
		oid_result->val.string[1] = vars->val.string[1];
		oid_result->val.string[2] = vars->val.string[2];
		oid_result->val.string[3] = vars->val.string[3];
		return;
	}
	
	if (vars->type == ASN_OPAQUE_I64) {
		printI64(oid_result->val.string, vars->val.counter64);
		return;
	}
	
	if (vars->type == ASN_OPAQUE_COUNTER64 || vars->type == ASN_OPAQUE_U64 || vars->type == ASN_COUNTER64) {
		printU64(oid_result->val.string, vars->val.counter64);
		return;
	}

	if (vars->type == ASN_COUNTER) {
		oid_result->val.integer = *vars->val.integer;
		return;
	}

	if (vars->type == ASN_GAUGE) {
		oid_result->val.integer = *vars->val.integer;
		return;
	}

	if (vars->type == ASN_OPAQUE_FLOAT) {
		oid_result->val.floatVal = *vars->val.floatVal;
		return;
	}
	
	if (vars->type == ASN_OPAQUE_DOUBLE) {
		oid_result->val.doubleVal = *vars->val.doubleVal;
		return;
	}
	
	if (vars->type == ASN_NULL) {
		return;
	}
}
Exemplo n.º 5
0
/* Handling of results */
static void noit_snmp_log_results(noit_module_t *self, noit_check_t *check,
                                  struct snmp_pdu *pdu) {
  struct check_info *info = check->closure;
  struct variable_list *vars;
  struct timeval duration;
  char buff[128];
  stats_t current;
  int nresults = 0;

  noit_check_stats_clear(check, &current);

  if(pdu)
    for(vars = pdu->variables; vars; vars = vars->next_variable)
      nresults++;

  gettimeofday(&current.whence, NULL);
  sub_timeval(current.whence, check->last_fire_time, &duration);
  current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;
  current.available = pdu ? NP_AVAILABLE : NP_UNAVAILABLE;
  current.state = (nresults == info->noids) ? NP_GOOD : NP_BAD;
  snprintf(buff, sizeof(buff), "%d/%d gets", nresults, info->noids);
  current.status = buff;

  /* We have no results over which to iterate. */
  if(!pdu) {
    noit_check_set_stats(check, &current);
    return;
  }

  /* manipulate the information ourselves */
  nresults = 0;
  for(vars = pdu->variables; vars; vars = vars->next_variable) {
    char *sp;
    int oid_idx;
    double float_conv;
    u_int64_t u64;
    int64_t i64;
    char *endptr;
    char varbuff[256];

    /* find the oid to which this is the response */
    oid_idx = nresults; /* our current idx is the most likely */
    if(info->oids[oid_idx].oidlen != vars->name_length ||
       memcmp(info->oids[oid_idx].oid, vars->name,
              vars->name_length * sizeof(oid))) {
      /* Not the most obvious guess */
      for(oid_idx = info->noids - 1; oid_idx >= 0; oid_idx--) {
        if(info->oids[oid_idx].oidlen == vars->name_length &&
           memcmp(info->oids[oid_idx].oid, vars->name,
                  vars->name_length * sizeof(oid))) break;
      }
    }
    if(oid_idx < 0) {
      snprint_variable(varbuff, sizeof(varbuff),
                       vars->name, vars->name_length, vars);
      noitL(nlerr, "Unexpected oid results to %s`%s`%s: %s\n",
            check->target, check->module, check->name, varbuff);
      nresults++;
      continue;
    }

#define SETM(a,b) noit_stats_set_metric(check, &current, \
                                        info->oids[oid_idx].confname, a, b)
    if(info->oids[oid_idx].type_should_override) {
      snprint_value(varbuff, sizeof(varbuff), vars->name, vars->name_length, vars);
      sp = strchr(varbuff, ' ');
      if(sp) sp++;
      noit_stats_set_metric_coerce(check, &current, info->oids[oid_idx].confname,
                                   info->oids[oid_idx].type_override,
                                   sp);
    }
    else {
      switch(vars->type) {
        case ASN_OCTET_STR:
          sp = malloc(1 + vars->val_len);
          memcpy(sp, vars->val.string, vars->val_len);
          sp[vars->val_len] = '\0';
          SETM(METRIC_STRING, sp);
          free(sp);
          break;
        case ASN_INTEGER:
        case ASN_GAUGE:
          SETM(METRIC_INT32, vars->val.integer);
          break;
        case ASN_TIMETICKS:
        case ASN_COUNTER:
          SETM(METRIC_UINT32, vars->val.integer);
          break;
        case ASN_INTEGER64:
          printI64(varbuff, vars->val.counter64);
          i64 = strtoll(varbuff, &endptr, 10);
          SETM(METRIC_INT64, (varbuff == endptr) ? NULL : &i64);
          break;
        case ASN_COUNTER64:
          printU64(varbuff, vars->val.counter64);
          u64 = strtoull(varbuff, &endptr, 10);
          SETM(METRIC_UINT64, (varbuff == endptr) ? NULL : &u64);
          break;
        case ASN_FLOAT:
          if(vars->val.floatVal) float_conv = *(vars->val.floatVal);
          SETM(METRIC_DOUBLE, vars->val.floatVal ? &float_conv : NULL);
          break;
        case ASN_DOUBLE:
          SETM(METRIC_DOUBLE, vars->val.doubleVal);
          break;
        case SNMP_NOSUCHOBJECT:
        case SNMP_NOSUCHINSTANCE:
          SETM(METRIC_STRING, NULL);
          break;
        default:
          snprint_variable(varbuff, sizeof(varbuff), vars->name, vars->name_length, vars);
          /* Advance passed the first space and use that unless there
           * is no space or we have no more string left.
           */
          sp = strchr(varbuff, ' ');
          if(sp) sp++;
          SETM(METRIC_STRING, (sp && *sp) ? sp : NULL);
      }
    }
    nresults++;
  }
  noit_check_set_stats(check, &current);
}