/** * 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); }
/** * 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; }
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); }
/** * 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; } }
/* 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, ¤t); if(pdu) for(vars = pdu->variables; vars; vars = vars->next_variable) nresults++; gettimeofday(¤t.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, ¤t); 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, ¤t, \ 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, ¤t, 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, ¤t); }