/* * simple printing of returned data */ int snmpStoreResult (tSession *session, struct snmp_pdu *pdu, char **result) { char buf[RESULTSIZE]; struct variable_list *vp; struct snmp_session *sp = session->sess; unsigned int o = session->current_oid; unsigned int i,j; *result = (char*)calloc(RESULTSIZE+1, sizeof(char)); vp = pdu->variables; if (pdu->errstat == SNMP_ERR_NOERROR) { while (vp) { snprint_value(*result, RESULTSIZE, vp->name, vp->name_length, vp); // tolower & remove spaces and linebreaks for (i=0, j=0; i<strlen(*result); i++) { if ((*result)[i] > 0x22) { if ((*result)[i] >= 0x41 && (*result)[i] <= 0x5A) { (*result)[j] = (*result)[i] + 0x20; } else { (*result)[j] = (*result)[i]; } j++; } } (*result)[j] = 0; // fix lancom snr if (session->oidList.oid[o].id_oidtype == 12 && ( session->oidList.oid[o].id_type == 2 || session->oidList.oid[o].id_type == 5 || session->oidList.oid[o].id_type == 9 || session->oidList.oid[o].id_type == 24 )) { snprintf(*result, RESULTSIZE, "%.0f", atoi(*result) * 0.64); } snprint_variable(buf, sizeof(buf), vp->name, vp->name_length, vp); syslog(LOG_DEBUG, "snmpStoreResult: %s: %s", sp->peername, buf); vp = vp->next_variable; } return 1; } else { if (vp) { snprint_objid(buf, sizeof(buf), vp->name, vp->name_length); } else { strcpy(buf, "(empty buf)"); } syslog(LOG_ERR, "snmpStoreResult: %s: %s: (%s)", sp->peername, buf, snmp_errstring(pdu->errstat)); if (pdu->errstat == SNMP_ERR_NOSUCHNAME) { snprintf(*result, RESULTSIZE, "U"); return 1; } return 0; } }
static char *snmp_get_octet_string(struct variable_list *vars) { const char *__function_name = "snmp_get_octet_string"; static char buf[MAX_STRING_LEN]; const char *hint; char *strval_dyn = NULL, is_hex = 0; size_t offset = 0; struct tree *subtree; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); /* find the subtree to get display hint */ subtree = get_tree(vars->name, vars->name_length, get_tree_head()); hint = subtree ? subtree->hint : NULL; /* we will decide if we want the value from vars->val or what snprint_value() returned later */ if (-1 == snprint_value(buf, sizeof(buf), vars->name, vars->name_length, vars)) goto end; zabbix_log(LOG_LEVEL_DEBUG, "%s() full value:'%s'", __function_name, buf); /* decide if it's Hex, offset will be possibly needed later */ if (0 == strncmp(buf, "Hex-STRING: ", 12)) { is_hex = 1; offset = 12; } /* in case of no hex and no display hint take the value from */ /* vars->val, it contains unquoted and unescaped string */ if (0 == is_hex && NULL == hint) { strval_dyn = zbx_malloc(strval_dyn, vars->val_len + 1); memcpy(strval_dyn, vars->val.string, vars->val_len); strval_dyn[vars->val_len] = '\0'; } else { if (0 == is_hex && 0 == strncmp(buf, "STRING: ", 8)) offset = 8; strval_dyn = zbx_strdup(strval_dyn, buf + offset); } zbx_rtrim(strval_dyn, ZBX_WHITESPACE); zbx_ltrim(strval_dyn, ZBX_WHITESPACE); end: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():'%s'", __function_name, strval_dyn ? strval_dyn : "(null)"); return strval_dyn; }
int handle_snmp_event(struct oflops_context * ctx, struct snmp_event * se) { netsnmp_variable_list *vars; int len = 1024; char msg[1024], log[1024]; struct timeval now; int i; gettimeofday(&now, NULL); for(vars = se->pdu->variables; vars; vars = vars->next_variable) { snprint_value(msg, len, vars->name, vars->name_length, vars); if((vars->name_length == ctx->cpuOID_len) && (memcmp(vars->name, ctx->cpuOID, ctx->cpuOID_len * sizeof(oid)) == 0) ) { snprintf(log, len, "cpu : %s %%", msg); oflops_log(now, SNMP_MSG, log); } else { for(i=0;i<ctx->n_channels;i++) { if((vars->name_length == ctx->channels[i].inOID_len) && (memcmp(vars->name, ctx->channels[i].inOID, ctx->channels[i].inOID_len * sizeof(oid)) == 0) ) { snprintf(log, len, "port %d : rx %s pkts", (int)ctx->channels[i].outOID[ctx->channels[i].outOID_len-1], msg); oflops_log(now, SNMP_MSG, log); break; } if((vars->name_length == ctx->channels[i].outOID_len) && (memcmp(vars->name, ctx->channels[i].outOID, ctx->channels[i].outOID_len * sizeof(oid))==0) ) { snprintf(log, len, "port %d : tx %s pkts", (int)ctx->channels[i].outOID[ctx->channels[i].outOID_len-1], msg); oflops_log(now, SNMP_MSG, log); break; } } //for }// if cpu }// variable iterator return 0; }
/*int get_value_snmp(double *result,char *result_str,DB_ITEM *item,char *error, int max_error_len)*/ int get_value_snmp(DB_ITEM *item, AGENT_RESULT *value) { #define NEW_APPROACH struct snmp_session session, *ss; struct snmp_pdu *pdu; struct snmp_pdu *response; #ifdef NEW_APPROACH char temp[MAX_STRING_LEN]; #endif oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; struct variable_list *vars; int status; char *p, *c; double dbl; unsigned char *ip; char error[MAX_STRING_LEN]; int ret=SUCCEED; zabbix_log( LOG_LEVEL_DEBUG, "In get_value_SNMP()"); init_result(value); /* assert((item->type == ITEM_TYPE_SNMPv1)||(item->type == ITEM_TYPE_SNMPv2c)); */ assert((item->type == ITEM_TYPE_SNMPv1)||(item->type == ITEM_TYPE_SNMPv2c)||(item->type == ITEM_TYPE_SNMPv3)); snmp_sess_init( &session ); /* session.version = version;*/ if(item->type == ITEM_TYPE_SNMPv1) { session.version = SNMP_VERSION_1; } else if(item->type == ITEM_TYPE_SNMPv2c) { session.version = SNMP_VERSION_2c; } else if(item->type == ITEM_TYPE_SNMPv3) { session.version = SNMP_VERSION_3; } else { zbx_snprintf(error,sizeof(error),"Error in get_value_SNMP. Wrong item type [%d]. Must be SNMP.", item->type); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); return NOTSUPPORTED; } if(item->useip == 1) { #ifdef NEW_APPROACH zbx_snprintf(temp,sizeof(temp),"%s:%d", item->host_ip, item->snmp_port); session.peername = temp; session.remote_port = item->snmp_port; #else session.peername = item->host_ip; session.remote_port = item->snmp_port; #endif } else { #ifdef NEW_APPROACH zbx_snprintf(temp, sizeof(temp), "%s:%d", item->host_dns, item->snmp_port); session.peername = temp; session.remote_port = item->snmp_port; #else session.peername = item->host_dns; session.remote_port = item->snmp_port; #endif } if( (session.version == SNMP_VERSION_1) || (item->type == ITEM_TYPE_SNMPv2c)) { session.community = (u_char *)item->snmp_community; session.community_len = strlen((void *)session.community); zabbix_log( LOG_LEVEL_DEBUG, "SNMP [%s@%s:%d]", session.community, session.peername, session.remote_port); } else if(session.version == SNMP_VERSION_3) { /* set the SNMPv3 user name */ session.securityName = item->snmpv3_securityname; session.securityNameLen = strlen(session.securityName); /* set the security level to authenticated, but not encrypted */ if(item->snmpv3_securitylevel == ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV) { session.securityLevel = SNMP_SEC_LEVEL_NOAUTH; } else if(item->snmpv3_securitylevel == ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV) { session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; /* set the authentication method to MD5 */ session.securityAuthProto = usmHMACMD5AuthProtocol; session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; session.securityAuthKeyLen = USM_AUTH_KU_LEN; if (generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) item->snmpv3_authpassphrase, strlen(item->snmpv3_authpassphrase), session.securityAuthKey, &session.securityAuthKeyLen) != SNMPERR_SUCCESS) { zbx_snprintf(error,sizeof(error),"Error generating Ku from authentication pass phrase."); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); return NOTSUPPORTED; } } else if(item->snmpv3_securitylevel == ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV) { session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; /* set the authentication method to MD5 */ session.securityAuthProto = usmHMACMD5AuthProtocol; session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; session.securityAuthKeyLen = USM_AUTH_KU_LEN; if (generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) item->snmpv3_authpassphrase, strlen(item->snmpv3_authpassphrase), session.securityAuthKey, &session.securityAuthKeyLen) != SNMPERR_SUCCESS) { zbx_snprintf(error,sizeof(error),"Error generating Ku from authentication pass phrase."); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); return NOTSUPPORTED; } /* set the private method to DES */ session.securityPrivProto = usmDESPrivProtocol; session.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; session.securityPrivKeyLen = USM_PRIV_KU_LEN; if (generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) item->snmpv3_privpassphrase, strlen(item->snmpv3_privpassphrase), session.securityPrivKey, &session.securityPrivKeyLen) != SNMPERR_SUCCESS) { zbx_snprintf(error,sizeof(error),"Error generating Ku from priv pass phrase."); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); return NOTSUPPORTED; } } zabbix_log( LOG_LEVEL_DEBUG, "SNMPv3 [%s@%s:%d]", session.securityName, session.peername, session.remote_port); } else { zbx_snprintf(error,sizeof(error),"Error in get_value_SNMP. Unsupported session.version [%d]", (int)session.version); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); return NOTSUPPORTED; } zabbix_log( LOG_LEVEL_DEBUG, "OID [%s]", item->snmp_oid); SOCK_STARTUP; ss = snmp_open(&session); if(ss == NULL) { SOCK_CLEANUP; zbx_snprintf(error,sizeof(error),"Error doing snmp_open()"); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); return NOTSUPPORTED; } zabbix_log( LOG_LEVEL_DEBUG, "In get_value_SNMP() 0.2"); pdu = snmp_pdu_create(SNMP_MSG_GET); /* Changed to snmp_parse_oid */ /* read_objid(item->snmp_oid, anOID, &anOID_len);*/ snmp_parse_oid(item->snmp_oid, anOID, &anOID_len); #if OTHER_METHODS get_node("sysDescr.0", anOID, &anOID_len); read_objid(".1.3.6.1.2.1.1.1.0", anOID, &anOID_len); read_objid("system.sysDescr.0", anOID, &anOID_len); #endif snmp_add_null_var(pdu, anOID, anOID_len); zabbix_log( LOG_LEVEL_DEBUG, "In get_value_SNMP() 0.3"); status = snmp_synch_response(ss, pdu, &response); zabbix_log( LOG_LEVEL_DEBUG, "Status send [%d]", status); zabbix_log( LOG_LEVEL_DEBUG, "In get_value_SNMP() 0.4"); zabbix_log( LOG_LEVEL_DEBUG, "In get_value_SNMP() 1"); if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { zabbix_log( LOG_LEVEL_DEBUG, "In get_value_SNMP() 2"); /* for(vars = response->variables; vars; vars = vars->next_variable) { print_variable(vars->name, vars->name_length, vars); }*/ for(vars = response->variables; vars; vars = vars->next_variable) { int count=1; zabbix_log( LOG_LEVEL_DEBUG, "AV loop(%d)", vars->type); /* if( (vars->type == ASN_INTEGER) ||*/ if( (vars->type == ASN_UINTEGER)|| (vars->type == ASN_COUNTER) || #ifdef OPAQUE_SPECIAL_TYPES (vars->type == ASN_UNSIGNED64) || #endif (vars->type == ASN_TIMETICKS) || (vars->type == ASN_GAUGE) ) { /* *result=(long)*vars->val.integer;*/ /* * This solves situation when large numbers are stored as negative values * http://sourceforge.net/tracker/index.php?func=detail&aid=700145&group_id=23494&atid=378683 */ /*zbx_snprintf(result_str,sizeof(result_str),"%ld",(long)*vars->val.integer);*/ /* zbx_snprintf(result_str,sizeof(result_str),"%lu",(long)*vars->val.integer);*/ /* Not correct. Returns huge values. */ /* SET_UI64_RESULT(value, (zbx_uint64_t)*vars->val.integer);*/ if (vars->type == ASN_GAUGE && *vars->val.integer >= 4294967294) { SET_UI64_RESULT(value, (unsigned long)0); } else { SET_UI64_RESULT(value, (unsigned long)*vars->val.integer); } zabbix_log( LOG_LEVEL_DEBUG, "OID [%s] Type [%d] UI64[" ZBX_FS_UI64 "]", item->snmp_oid, vars->type, (zbx_uint64_t)*vars->val.integer); zabbix_log( LOG_LEVEL_DEBUG, "OID [%s] Type [%d] ULONG[%lu]", item->snmp_oid, vars->type, (zbx_uint64_t)(unsigned long)*vars->val.integer); } else if(vars->type == ASN_COUNTER64) { /* Incorrect code for 32 bit platforms */ /* SET_UI64_RESULT(value, ((vars->val.counter64->high)<<32)+(vars->val.counter64->low));*/ SET_UI64_RESULT(value, (((zbx_uint64_t)vars->val.counter64->high)<<32)+((zbx_uint64_t)vars->val.counter64->low)); } else if(vars->type == ASN_INTEGER #define ASN_FLOAT (ASN_APPLICATION | 8) #define ASN_DOUBLE (ASN_APPLICATION | 9) #ifdef OPAQUE_SPECIAL_TYPES || (vars->type == ASN_INTEGER64) #endif ) { /* Negative integer values are converted to double */ if(*vars->val.integer<0) { SET_DBL_RESULT(value, (double)*vars->val.integer); } else { SET_UI64_RESULT(value, (zbx_uint64_t)*vars->val.integer); } } #ifdef OPAQUE_SPECIAL_TYPES else if(vars->type == ASN_FLOAT) { SET_DBL_RESULT(value, *vars->val.floatVal); } else if(vars->type == ASN_DOUBLE) { SET_DBL_RESULT(value, *vars->val.doubleVal); } #endif else if(vars->type == ASN_OCTET_STR) { if(item->value_type == ITEM_VALUE_TYPE_FLOAT) { p = malloc(vars->val_len+1); if(p) { memcpy(p, vars->val.string, vars->val_len); p[vars->val_len] = '\0'; dbl = strtod(p, NULL); SET_DBL_RESULT(value, dbl); } else { zbx_snprintf(error,sizeof(error),"Cannot allocate required memory"); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); } } else if(item->value_type != ITEM_VALUE_TYPE_STR) { zbx_snprintf(error,sizeof(error),"Cannot store SNMP string value (ASN_OCTET_STR) in item having numeric type"); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); ret = NOTSUPPORTED; } else { zabbix_log( LOG_LEVEL_DEBUG, "ASN_OCTET_STR [%s]", vars->val.string); zabbix_log( LOG_LEVEL_DEBUG, "ASN_OCTET_STR [%d]", vars->val_len); p = malloc(1024); if(p) { memset(p,0,1024); snprint_value(p, 1023, vars->name, vars->name_length, vars); /* Skip STRING: and STRING_HEX: */ c=strchr(p,':'); if(c==NULL) { SET_STR_RESULT(value, strdup(p)); } else { SET_STR_RESULT(value, strdup(c+1)); } zabbix_log( LOG_LEVEL_DEBUG, "ASN_OCTET_STR [%s]", p); free(p); } else { zbx_snprintf(error,MAX_STRING_LEN-1,"Cannot allocate required memory"); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); } /* p = malloc(vars->val_len+1); if(p) { zabbix_log( LOG_LEVEL_WARNING, "Result [%s] len [%d]",vars->val.string,vars->val_len); memcpy(p, vars->val.string, vars->val_len); p[vars->val_len] = '\0'; SET_STR_RESULT(value, p); } else { zbx_snprintf(error,sizeof(error),"Cannot allocate required memory"); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); }*/ } } else if(vars->type == ASN_IPADDRESS) { /* ip = vars->val.string; zbx_snprintf(result_str,sizeof(result_str),"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);*/ /* if(item->type == 0) { ret = NOTSUPPORTED; }*/ if(item->value_type != ITEM_VALUE_TYPE_STR) { zbx_snprintf(error,sizeof(error),"Cannot store SNMP string value (ASN_IPADDRESS) in item having numeric type"); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); ret = NOTSUPPORTED; } else { p = malloc(MAX_STRING_LEN); if(p) { ip = vars->val.string; zbx_snprintf(p,MAX_STRING_LEN-1,"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); SET_STR_RESULT(value, p); } else { zbx_snprintf(error,MAX_STRING_LEN-1,"Cannot allocate required memory"); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); } } } else { /* count is not really used. Has to be removed */ count++; zbx_snprintf(error,sizeof(error),"OID [%s] value #%d has unknow type [%X]", item->snmp_oid, count, vars->type); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); ret = NOTSUPPORTED; } } } else { if (status == STAT_SUCCESS) { zabbix_log( LOG_LEVEL_WARNING, "SNMP error in packet. Reason: %s\n", snmp_errstring(response->errstat)); if(response->errstat == SNMP_ERR_NOSUCHNAME) { zbx_snprintf(error,sizeof(error),"SNMP error [%s]", snmp_errstring(response->errstat)); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); ret=NOTSUPPORTED; } else { zbx_snprintf(error,sizeof(error),"SNMP error [%s]", snmp_errstring(response->errstat)); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); ret=NOTSUPPORTED; } } else if(status == STAT_TIMEOUT) { zbx_snprintf(error,sizeof(error),"Timeout while connecting to [%s]", session.peername); /* snmp_sess_perror("snmpget", ss);*/ zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); ret = NETWORK_ERROR; } else { zbx_snprintf(error,sizeof(error),"SNMP error [%d]", status); zabbix_log( LOG_LEVEL_ERR, "%s", error); SET_MSG_RESULT(value, strdup(error)); ret=NOTSUPPORTED; } } if (response) { snmp_free_pdu(response); } snmp_close(ss); SOCK_CLEANUP; return ret; }
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) */ }
int decode_vbind (unsigned char *data, unsigned int vb_len) { unsigned char *var_val; oid var_name[MAX_OID_LEN]; /* To test the objid */ size_t name_len = MAX_OID_LEN; /* To test the objid */ int badtype=0; size_t len; struct variable_list *vp; oid objid[MAX_OID_LEN]; char _docsis_snmp_label[50]; /* To hold the 'name' of the type, i.e. Integer etc */ char *enum_string = NULL; static char outbuf[16384]; struct tree *subtree; struct enum_list *enums; memset (outbuf, 0, 16384); vp = (struct variable_list *) malloc (sizeof (struct variable_list)); if (vp == NULL) { fprintf (stderr, "Out of memory\n"); return 0; } memset (vp, 0, sizeof (struct variable_list)); vp->next_variable = NULL; vp->val.string = NULL; vp->name_length = MAX_OID_LEN; vp->name = 0; data = snmp_parse_var_op (data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (size_t *) & vb_len); if (data == NULL) return -1; if (snmp_set_var_objid (vp, objid, vp->name_length)) return -1; len = PACKET_LENGTH; if (netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX); } /* Disable extended index format ... makes it harder to parse tokens in lex */ if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM); } /* Enable printing numeric enums */ if (netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES); } /* Disable escape quotes in string index output */ netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_SUFFIX); if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_OID_OUTPUT_NUMERIC)) { netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC); } snprint_objid (outbuf, 1023, vp->name, vp->name_length); if (!get_node (outbuf, var_name, &name_len)) { if (!read_objid (outbuf, var_name, &name_len)) { fprintf (stderr, "/* Hmm ... can't find oid %s at line %d ... perhaps the MIBs are not installed ? */\n", outbuf, line); /* temporarily set full output format */ netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_FULL); memset (outbuf, 0, 1024); snprint_objid (outbuf, 1023, vp->name, vp->name_length); /* Go back to suffix-mode for better readability */ netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_SUFFIX); } } printf("%s", outbuf); /* save the subtree - we need it later to show enums */ subtree = get_tree (var_name, name_len, get_tree_head() ); /* This first switch is just for saving the type in the format we actually want to print. */ switch ((short) vp->type) { case ASN_INTEGER: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Integer"); break; case ASN_COUNTER: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Counter32"); break; case ASN_GAUGE: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Gauge32"); break; case ASN_TIMETICKS: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "TimeTicks"); break; case ASN_UINTEGER: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Unsigned32"); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_COUNTER64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueCounter64"); break; case ASN_OPAQUE_U64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueU64"); break; #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_COUNTER64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Counter64"); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_FLOAT: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueFloat"); break; case ASN_OPAQUE_DOUBLE: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueDouble"); break; case ASN_OPAQUE_I64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueI64"); break; #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_OCTET_STR: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "String"); break; case ASN_IPADDRESS: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "IPAddress"); break; case ASN_OPAQUE: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Opaque"); break; case ASN_NSAP: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "NSAP"); break; case ASN_OBJECT_ID: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "ObjectID"); break; case ASN_BIT_STR: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "BitString"); break; } switch ((short) vp->type) { case ASN_INTEGER: vp->val.integer = (long *) vp->buf; vp->val_len = sizeof (long); asn_parse_int (var_val, &len, &vp->type, (long *) vp->val.integer, sizeof (vp->val.integer)); break; case ASN_COUNTER: case ASN_GAUGE: case ASN_TIMETICKS: case ASN_UINTEGER: vp->val.integer = (long *) vp->buf; vp->val_len = sizeof (u_long); asn_parse_unsigned_int (var_val, &len, &vp->type, (u_long *) vp->val.integer, sizeof (vp->val.integer)); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_COUNTER64: case ASN_OPAQUE_U64: #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_COUNTER64: vp->val.counter64 = (struct counter64 *) vp->buf; vp->val_len = sizeof (struct counter64); asn_parse_unsigned_int64 (var_val, &len, &vp->type, (struct counter64 *) vp->val.counter64, sizeof (*vp->val.counter64)); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_FLOAT: vp->val.floatVal = (float *) vp->buf; vp->val_len = sizeof (float); asn_parse_float (var_val, &len, &vp->type, vp->val.floatVal, vp->val_len); break; case ASN_OPAQUE_DOUBLE: vp->val.doubleVal = (double *) vp->buf; vp->val_len = sizeof (double); asn_parse_double (var_val, &len, &vp->type, vp->val.doubleVal, vp->val_len); break; case ASN_OPAQUE_I64: vp->val.counter64 = (struct counter64 *) vp->buf; vp->val_len = sizeof (struct counter64); asn_parse_signed_int64 (var_val, &len, &vp->type, (struct counter64 *) vp->val.counter64, sizeof (*vp->val.counter64)); break; #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_OCTET_STR: case ASN_IPADDRESS: case ASN_OPAQUE: case ASN_NSAP: if (vp->val_len < sizeof (vp->buf)) { vp->val.string = (u_char *) vp->buf; } else { vp->val.string = (u_char *) malloc ((unsigned) vp->val_len+1); memset(vp->val.string, 0, vp->val_len+1); } asn_parse_string (var_val, &len, &vp->type, vp->val.string, &vp->val_len); break; case ASN_OBJECT_ID: vp->val_len = MAX_OID_LEN; asn_parse_objid (var_val, &len, &vp->type, objid, &vp->val_len); vp->val_len *= sizeof (oid); vp->val.objid = (oid *) malloc ((unsigned) vp->val_len); memmove (vp->val.objid, objid, vp->val_len); break; case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: case SNMP_ENDOFMIBVIEW: case ASN_NULL: break; case ASN_BIT_STR: vp->val.bitstring = (u_char *) malloc (vp->val_len); asn_parse_bitstring (var_val, &len, &vp->type, vp->val.bitstring, &vp->val_len); break; default: fprintf(stderr, "Error: bad type returned (%x)\n", vp->type); badtype = 1; break; } if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID); } if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS); } if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); } if (!strcmp (_docsis_snmp_label, "String")) /* Strings need special treatment - see below */ { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES); } switch ((short) vp->type) { case ASN_OCTET_STR: if (str_isprint((char *) vp->val.string, vp->val_len)) { snprintf(outbuf, vp->val_len+5, "\"%s\"", vp->val.string); } else { snprint_hexadecimal (outbuf, 16383, (char *) vp->val.string, vp->val_len); memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "HexString"); } break; case ASN_BIT_STR: snprint_hexadecimal (outbuf, 1023, (char *) vp->val.bitstring, vp->val_len); break; case ASN_OBJECT_ID: netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC); snprint_value (outbuf, 1023, vp->name, vp->name_length, vp); netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_SUFFIX); break; default: snprint_value (outbuf, 1023, vp->name, vp->name_length, vp); } if ( subtree ) { enums = subtree->enums; for (; enums; enums = enums->next) { if (enums->value == *vp->val.integer) { enum_string = enums->label; break; } } } if (enum_string) printf(" %s %s; /* %s */", _docsis_snmp_label, outbuf, enum_string); else printf(" %s %s;", _docsis_snmp_label, outbuf); snmp_free_var (vp); return badtype; }
static int snmp_get_rssi_cb(int operation, struct snmp_session *sp, int reqid, struct snmp_pdu *pdu, void *magic) { char value[15] = {0,}; char *endptr = NULL; int value_num = 0; struct variable_list *vars = NULL; repeater_t *repeater = NULL; in_addr_t ipaddr; flag_t dodbupdate = 0; if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { if (pdu->errstat == SNMP_ERR_NOERROR) { ipaddr = inet_addr(sp->peername); repeater = repeaters_findbyip((struct in_addr *)&ipaddr); for (vars = pdu->variables; vars; vars = vars->next_variable) { if (netsnmp_oid_equals(vars->name, vars->name_length, oid_rssi_ts1, oid_rssi_ts1_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG LOGLEVEL_SNMP "snmp: invalid ts1 rssi value received: %s\n", sp->peername); else { if (value_num > -200) { if (repeater != NULL) { repeater->slot[0].rssi = value_num; if (repeater->slot[0].avg_rssi == 0) repeater->slot[0].avg_rssi = value_num; else repeater->slot[0].avg_rssi = (repeater->slot[0].avg_rssi+value_num)/2.0; dodbupdate = 1; } console_log(LOGLEVEL_SNMP "snmp [%s]: got ts1 rssi value %d\n", sp->peername, value_num); } } } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_rssi_ts2, oid_rssi_ts2_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG LOGLEVEL_SNMP "snmp: invalid ts2 rssi value received: %s\n", value); else { if (value_num > -200) { if (repeater != NULL) { repeater->slot[1].rssi = value_num; if (repeater->slot[1].avg_rssi == 0) repeater->slot[1].avg_rssi = value_num; else repeater->slot[1].avg_rssi = (repeater->slot[1].avg_rssi+value_num)/2.0; dodbupdate = 1; } console_log(LOGLEVEL_SNMP "snmp [%s]: got ts2 rssi value %d\n", sp->peername, value_num); } } } } if (dodbupdate) remotedb_update(repeater); snmp_rssi_received = 1; } else console_log(LOGLEVEL_DEBUG "snmp: rssi read error\n"); } else console_log(LOGLEVEL_DEBUG "snmp: rssi read timeout\n"); return 1; }
static int snmp_get_repeaterinfo_cb(int operation, struct snmp_session *sp, int reqid, struct snmp_pdu *pdu, void *magic) { char value[200] = {0,}; char *endptr = NULL; int value_num = 0; struct variable_list *vars = NULL; repeater_t *repeater = NULL; in_addr_t ipaddr; char value_utf16[sizeof(value)/2] = {0,}; char value_utf8[sizeof(value_utf16)/2] = {0,}; int length = 0; flag_t dodbupdate = 0; if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { if (pdu->errstat == SNMP_ERR_NOERROR) { ipaddr = inet_addr(sp->peername); repeater = repeaters_findbyip((struct in_addr *)&ipaddr); for (vars = pdu->variables; vars; vars = vars->next_variable) { if (netsnmp_oid_equals(vars->name, vars->name_length, oid_id, oid_id_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG "snmp [%s]: invalid id value received: %s\n", sp->peername, value); else { if (repeater != NULL) { repeater->id = value_num; dodbupdate = 1; } console_log("snmp [%s]: got id value %d\n", sp->peername, value_num); } } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_repeatertype, oid_repeatertype_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); length = snmp_hexstring_to_bytearray(value+12, value_utf16, sizeof(value_utf16)); // +12: cutting "Hex-STRING: " text returned by snprint_value(). snmp_utf16_to_utf8(value_utf16, length, value_utf8, sizeof(value_utf8)); if (repeater != NULL) { strncpy(repeater->type, value_utf8, sizeof(repeater->type)); dodbupdate = 1; } console_log("snmp [%s]: got repeater type value %s\n", sp->peername, value_utf8); } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_fwversion, oid_fwversion_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); length = snmp_hexstring_to_bytearray(value+12, value_utf16, sizeof(value_utf16)); // +12: cutting "Hex-STRING: " text returned by snprint_value(). snmp_utf16_to_utf8(value_utf16, length, value_utf8, sizeof(value_utf8)); if (repeater != NULL) { strncpy(repeater->fwversion, value_utf8, sizeof(repeater->fwversion)); dodbupdate = 1; } console_log("snmp [%s]: got repeater fw version value %s\n", sp->peername, value_utf8); } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_callsign, oid_callsign_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); length = snmp_hexstring_to_bytearray(value+12, value_utf16, sizeof(value_utf16)); // +12: cutting "Hex-STRING: " text returned by snprint_value(). snmp_utf16_to_utf8(value_utf16, length, value_utf8, sizeof(value_utf8)); if (repeater != NULL) { strncpy(repeater->callsign, value_utf8, sizeof(repeater->callsign)); dodbupdate = 1; } console_log("snmp [%s]: got repeater callsign value %s\n", sp->peername, value_utf8); } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_dlfreq, oid_dlfreq_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG "snmp [%s]: invalid dl freq value received: %s\n", sp->peername, value); else { if (repeater != NULL) { repeater->dlfreq = value_num; dodbupdate = 1; } console_log("snmp [%s]: got dl freq value %d\n", sp->peername, value_num); } } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_ulfreq, oid_ulfreq_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG "snmp [%s]: invalid dl freq value received: %s\n", sp->peername, value); else { if (repeater != NULL) { repeater->ulfreq = value_num; dodbupdate = 1; } console_log("snmp [%s]: got ul freq value %d\n", sp->peername, value_num); } } } if (dodbupdate) remotedb_update_repeater(repeater); snmp_repeaterinfo_received = 1; } else console_log(LOGLEVEL_DEBUG "snmp [%s]: repeater info read error\n", sp->peername); } else console_log(LOGLEVEL_DEBUG "snmp [%s]: repeater info read timeout\n", sp->peername); return 1; }
/*! \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; }
/* 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); }
/////////////////////////////////////////////////////////////// /// 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; }
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 }
void *poller(void *thread_args) { worker_t *worker = (worker_t *) thread_args; crew_t *crew = worker->crew; target_t *entry = NULL; void *sessp = NULL; struct snmp_session session; struct snmp_pdu *pdu = NULL; struct snmp_pdu *response = NULL; oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; struct variable_list *vars = NULL; unsigned long long result = 0; unsigned long long last_value = 0; unsigned long long insert_val = 0; int poll_status = 0, db_status = 0, bits = 0, init = 0; char query[BUFSIZE]; char storedoid[BUFSIZE]; char result_string[BUFSIZE]; int cur_work = 0; int prev_work = 99999999; int loop_count = 0; #ifdef FEATURES /* Per thread SQL connection testing */ #if HAVE_MYSQL MYSQL mysql; #elif HAVE_PGSQL PGconn *pgsql; #endif double rate = 0; struct timezone tzp; struct timeval current_time; struct timeval last_time; /* for thread settings */ int oldstate, oldtype; #endif debug(HIGH, "Thread [%d] starting.\n", worker->index); pthread_cleanup_push(cleanup_db, NULL); /* Attempt to connect to the MySQL Database */ #ifdef FEATURES /* Per thread MySQL connection testing */ if (!(set->dboff)) { /* load the database driver */ if (!(db_init(set))) { fatal("** Database error - check configuration.\n"); } /* connect to the database */ if (!(db_connect(set))) { fatal("server not responding.\n"); } /* set up cancel function for exit */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); } #endif /* FEATURES */ while (1) { /* if(loop_count >= POLLS_PER_TRANSACTION) { debug(HIGH, "Thread [%d] doing commit on %d\n", worker->index, POLLS_PER_TRANSACTION); db_status = db_commit(); loop_count = 0; } */ #ifdef FEATURES /* see if we've been cancelled before we start another loop */ pthread_testcancel(); #endif debug(DEVELOP, "Thread [%d] locking (wait on work)\n", worker->index); PT_MUTEX_LOCK(&crew->mutex); #ifdef FEATURES /* add an unlock to the cancel stack */ pthread_cleanup_push(cancel_lock, &crew->mutex); #endif while (current == NULL) { PT_COND_WAIT(&crew->go, &crew->mutex); } debug(DEVELOP, "Thread [%d] done waiting, received go (work cnt: %d)\n", worker->index, crew->work_count); cur_work = crew->work_count; /* if(cur_work > prev_work) { debug(HIGH, "Thread [%d] doing commit at %d\n", worker->index,time(NULL)); db_status = db_commit(); loop_count = 0; } */ prev_work = cur_work; if (current != NULL) { debug(DEVELOP, "Thread [%d] processing %s %s (%d work units remain in queue)\n", worker->index, current->host->host, current->objoid, crew->work_count); snmp_enable_stderrlog(); snmp_sess_init(&session); if (current->host->snmp_ver == 2) session.version = SNMP_VERSION_2c; else session.version = SNMP_VERSION_1; session.peername = current->host->host; session.community = current->host->community; session.remote_port = set->snmp_port; session.community_len = strlen(session.community); sessp = snmp_sess_open(&session); anOID_len = MAX_OID_LEN; pdu = snmp_pdu_create(SNMP_MSG_GET); read_objid(current->objoid, anOID, &anOID_len); entry = current; last_value = current->last_value; #ifdef FEATURES /* save the time so we can calculate rate */ last_time = current->last_time; #endif init = current->init; insert_val = 0; bits = current->bits; strncpy(storedoid, current->objoid, sizeof(storedoid)); current = getNext(); } debug(DEVELOP, "Thread [%d] unlocking (done grabbing current)\n", worker->index); PT_MUTEX_UNLOCK(&crew->mutex); #ifdef FEATURES /* take the unlock off the cancel stack */ pthread_cleanup_pop(FALSE); #endif snmp_add_null_var(pdu, anOID, anOID_len); if (sessp != NULL) poll_status = snmp_sess_synch_response(sessp, pdu, &response); else poll_status = STAT_DESCRIP_ERROR; /* Collect response and process stats */ PT_MUTEX_LOCK(&stats.mutex); if (poll_status == STAT_DESCRIP_ERROR) { stats.errors++; printf("*** SNMP Error: (%s) Bad descriptor.\n", session.peername); } else if (poll_status == STAT_TIMEOUT) { stats.no_resp++; printf("*** SNMP No response: (%s@%s).\n", session.peername, storedoid); } else if (poll_status != STAT_SUCCESS) { stats.errors++; printf("*** SNMP Error: (%s@%s) Unsuccessuful (%d).\n", session.peername, storedoid, poll_status); } else if (poll_status == STAT_SUCCESS && response->errstat != SNMP_ERR_NOERROR) { stats.errors++; printf("*** SNMP Error: (%s@%s) %s\n", session.peername, storedoid, snmp_errstring(response->errstat)); } else if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR && response->variables->type == SNMP_NOSUCHINSTANCE) { stats.errors++; printf("*** SNMP Error: No Such Instance Exists (%s@%s)\n", session.peername, storedoid); } else if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { stats.polls++; } PT_MUTEX_UNLOCK(&stats.mutex); /* Liftoff, successful poll, process it */ #ifdef FEATURES /* Get the current time */ gettimeofday(¤t_time, &tzp); #endif if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR && response->variables->type != SNMP_NOSUCHINSTANCE) { vars = response->variables; #ifdef OLD_UCD_SNMP sprint_value(result_string, anOID, anOID_len, vars); #else snprint_value(result_string, BUFSIZE, anOID, anOID_len, vars); #endif switch (vars->type) { /* * Switch over vars->type and modify/assign result accordingly. */ case ASN_COUNTER64: debug(DEBUG, "64-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = vars->val.counter64->high; result = result << 32; result = result + vars->val.counter64->low; break; case ASN_COUNTER: debug(DEBUG, "32-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_INTEGER: debug(DEBUG, "Integer result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_GAUGE: debug(DEBUG, "32-bit gauge: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_TIMETICKS: debug(DEBUG, "Timeticks result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_OPAQUE: debug(DEBUG, "Opaque result: (%s@%s) %s\n", session.peername, storedoid, result_string); result = (unsigned long) *(vars->val.integer); break; case ASN_OCTET_STR: debug(DEBUG, "String Result: (%s@%s) %s\n", session.peername, storedoid, result_string); #ifdef HAVE_STRTOLL result = strtoll(vars->val.string, NULL, 0); #else result = strtol(vars->val.string, NULL, 0); #endif break; default: debug(LOW, "Unknown result type: (%s@%s) %s\n", session.peername, storedoid, result_string); } /* Gauge Type */ if (bits == 0) { if (result != last_value) { insert_val = result; debug(DEVELOP, "Thread [%d]: Gauge change from %lld to %lld\n", worker->index, last_value, insert_val); } else { if (set->withzeros) insert_val = result; debug(DEVELOP, "Thread [%d]: Gauge steady at %lld\n", worker->index, insert_val); } /* Counter Wrap Condition */ } else if (result < last_value) { PT_MUTEX_LOCK(&stats.mutex); stats.wraps++; PT_MUTEX_UNLOCK(&stats.mutex); if (bits == 32) insert_val = (THIRTYTWO - last_value) + result; else if (bits == 64) insert_val = (SIXTYFOUR - last_value) + result; #ifdef FEATURES rate = insert_val / timediff(current_time, last_time); #endif debug(LOW, "*** Counter Wrap (%s@%s) [poll: %llu][last: %llu][insert: %llu]\n", session.peername, storedoid, result, last_value, insert_val); /* Not a counter wrap and this is not the first poll */ } else if ((last_value >= 0) && (init != NEW)) { insert_val = result - last_value; #ifdef FEATURES rate = insert_val / timediff(current_time, last_time); #endif /* Print out SNMP result if verbose */ if (set->verbose == DEBUG) printf("Thread [%d]: (%lld-%lld -- %llu) = %llu\n", worker->index, result, last_value, insert_val,rate); if (set->verbose == HIGH) printf("Thread [%d]: %llu\n", worker->index, insert_val); /* last_value < 0, so this must be the first poll */ } else { #ifdef FEATURES /* set up this result for the next poll */ entry->last_value = result; #endif debug(HIGH, "Thread [%d]: First Poll, Normalizing\n", worker->index); } /* Check for bogus data, either negative or unrealistic */ if (insert_val > entry->maxspeed || result < 0) { debug(LOW, "*** Out of Range (%s@%s) [insert_val: %llu] [oor: %lld]\n", session.peername, storedoid, insert_val, entry->maxspeed); insert_val = 0; #ifdef FEATURES rate = 0; #endif PT_MUTEX_LOCK(&stats.mutex); stats.out_of_range++; PT_MUTEX_UNLOCK(&stats.mutex); } if (!(set->dboff)) { if ( (insert_val > 0) || (set->withzeros) ) { #ifndef FEATURES /* MP - since we have our own database connection we don't need to lock it anymore */ PT_MUTEX_LOCK(&crew->mutex); #endif debug(DEVELOP, "db_insert sent: %s %d %d %e\n",entry->table,entry->iid,insert_val,rate); /* insert into the database */ db_status = db_insert(entry->table, entry->iid, insert_val, rate); #ifndef FEATURES /* MP - since we have our own database connection we don't need to lock it anymore */ PT_MUTEX_UNLOCK(&crew->mutex); #endif if (db_status) { PT_MUTEX_LOCK(&stats.mutex); stats.db_inserts++; PT_MUTEX_UNLOCK(&stats.mutex); } else { fatal("Fatal database error.\n"); } } /* insert_val > 0 or withzeros */ } /* !dboff */ } /* STAT_SUCCESS */ /* debug(HIGH, "Thread [%d] doing commit\n", worker->index); db_status = db_commit(); */ if (sessp != NULL) { snmp_sess_close(sessp); if (response != NULL) snmp_free_pdu(response); } debug(DEVELOP, "Thread [%d] locking (update work_count)\n", worker->index); PT_MUTEX_LOCK(&crew->mutex); crew->work_count--; /* Only if we received a positive result back do we update the last_value object */ if (poll_status == STAT_SUCCESS) { entry->last_value = result; if (init == NEW) entry->init = LIVE; } #ifdef FEATURES /* always update the time */ entry->last_time = current_time; #endif if (crew->work_count <= 0) { debug(HIGH, "Queue processed. Broadcasting thread done condition.\n"); PT_COND_BROAD(&crew->done); } debug(DEVELOP, "Thread [%d] unlocking (update work_count)\n", worker->index); PT_MUTEX_UNLOCK(&crew->mutex); loop_count++; } /* while(1) */ pthread_cleanup_pop(FALSE); /* Not reached */ }