void add_responses(struct variable_list *vars, struct oid_value ***next_ov, oid *name, size_t *name_length) { int found = 0; for (struct variable_list *var = vars; var; var = var->next_variable) { if (var->name_length < PRINTER_OID_LEN || 0 != netsnmp_oid_equals(PRINTER_OID, PRINTER_OID_LEN, var->name, PRINTER_OID_LEN)) { // This OID does not have the printer OID prefix, so we're done. *name_length = 0; return; } oid *objid = malloc(var->name_length * sizeof(oid)); memmove(objid, var->name, var->name_length * sizeof(oid)); size_t value_length = 1, out_length = 0;; char *value = malloc(value_length); sprint_realloc_value((unsigned char **)&value, &value_length, &out_length, 1, var->name, var->name_length, var); **next_ov = calloc(1, sizeof(struct oid_value)); (**next_ov)->name = objid; (**next_ov)->name_length = var->name_length; (**next_ov)->value = value; *next_ov = &(**next_ov)->next; *name_length = var->name_length; memmove(name, var->name, *name_length * sizeof(oid)); } return; }
/*! \fn void snmp_snprint_value(char *obuf, size_t buf_len, const oid *objid, size_t objidlen, struct variable_list *variable) * * \brief replacement for the buggy net-snmp.org snprint_value function * * This function format an output buffer with the correct string representation * of an snmp OID result fetched with snmp_get_multi. The buffer pointed to by * the function is modified. * */ void snmp_snprint_value(char *obuf, size_t buf_len, const oid *objid, size_t objidlen, struct variable_list *variable) { u_char *buf = NULL; size_t out_len = 0; if ((buf = (u_char *) calloc(buf_len, 1)) != 0) { if (sprint_realloc_value(&buf, &buf_len, &out_len, 1, objid, objidlen, variable)) { snprintf(obuf, buf_len, "%s", buf); }else{ snprintf(obuf, buf_len, "%s [TRUNCATED]", buf); } }else{ SET_UNDEFINED(obuf); } free(buf); }
/* * Store data received in response PDU */ int print_result (int status, req_t *req, struct snmp_pdu *pdu) { struct variable_list *vp; size_t len; keyrecord_t *kwalk; int keyoidlen; oid_t *owalk; int done; switch (status) { case STAT_SUCCESS: if (pdu->errstat == SNMP_ERR_NOERROR) { unsigned char *valstr = NULL, *oidstr = NULL; size_t valsz = 0, oidsz = 0; okcount++; switch (dataoperation) { case GET_KEYS: /* * Find the keyrecord currently processed for this request, and * look through the unresolved keys to see if we have a match. * If we do, determine the index for data retrieval. */ vp = pdu->variables; len = 0; sprint_realloc_value(&valstr, &valsz, &len, 1, vp->name, vp->name_length, vp); len = 0; sprint_realloc_objid(&oidstr, &oidsz, &len, 1, vp->name, vp->name_length); dbgprintf("Got key-oid '%s' = '%s'\n", oidstr, valstr); for (kwalk = req->currentkey, done = 0; (kwalk && !done); kwalk = kwalk->next) { /* Skip records where we have the result already, or that are not keyed */ if (kwalk->indexoid || (kwalk->indexmethod != req->currentkey->indexmethod)) { continue; } keyoidlen = strlen(req->currentkey->indexmethod->keyoid); switch (kwalk->indexmethod->idxtype) { case MIB_INDEX_IN_OID: /* Does the key match the value we just got? */ if (*kwalk->key == '*') { /* Match all. Add an extra key-record at the end. */ keyrecord_t *newkey; newkey = (keyrecord_t *)calloc(1, sizeof(keyrecord_t)); memcpy(newkey, kwalk, sizeof(keyrecord_t)); newkey->indexoid = strdup(oidstr + keyoidlen + 1); newkey->key = valstr; valstr = NULL; newkey->next = kwalk->next; kwalk->next = newkey; done = 1; } else if (strcmp(valstr, kwalk->key) == 0) { /* Grab the index part of the OID */ kwalk->indexoid = strdup(oidstr + keyoidlen + 1); done = 1; } break; case MIB_INDEX_IN_VALUE: /* Does the key match the index-part of the result OID? */ if (*kwalk->key == '*') { /* Match all. Add an extra key-record at the end. */ keyrecord_t *newkey; newkey = (keyrecord_t *)calloc(1, sizeof(keyrecord_t)); memcpy(newkey, kwalk, sizeof(keyrecord_t)); newkey->indexoid = valstr; valstr = NULL; newkey->key = strdup(oidstr + keyoidlen + 1); newkey->next = kwalk->next; kwalk->next = newkey; done = 1; } else if ((*(oidstr+keyoidlen) == '.') && (strcmp(oidstr+keyoidlen+1, kwalk->key)) == 0) { /* * Grab the index which is the value. * Avoid a strdup by grabbing the valstr pointer. */ kwalk->indexoid = valstr; valstr = NULL; valsz = 0; done = 1; } break; } } break; case GET_DATA: owalk = req->curr_oid; vp = pdu->variables; while (vp) { valsz = len = 0; sprint_realloc_value((unsigned char **)&owalk->result, &valsz, &len, 1, vp->name, vp->name_length, vp); owalk = owalk->next; vp = vp->next_variable; } break; } if (valstr) xfree(valstr); if (oidstr) xfree(oidstr); } else { errorcount++; errprintf("ERROR %s: %s\n", req->hostip[req->hostipidx], snmp_errstring(pdu->errstat)); } return 1; case STAT_TIMEOUT: timeoutcount++; dbgprintf("%s: Timeout\n", req->hostip); if (req->hostip[req->hostipidx+1]) { req->hostipidx++; startonehost(req, 1); } return 0; case STAT_ERROR: errorcount++; snmp_sess_perror(req->hostip[req->hostipidx], req->sess); return 0; } return 0; }
void getbulk_table_entries(netsnmp_session * ss) { int running = 1; netsnmp_pdu *pdu, *response; netsnmp_variable_list *vars, *last_var; int count; int status; int i; int row, col; char *buf = NULL; size_t buf_len = 0, out_len = 0; char *cp; char *name_p = NULL; char **dp; while (running) { /* * create PDU for GETBULK request and add object name to request */ pdu = snmp_pdu_create(SNMP_MSG_GETBULK); pdu->non_repeaters = 0; pdu->max_repetitions = max_getbulk; snmp_add_null_var(pdu, name, name_length); /* * do the request */ status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { /* * check resulting variables */ vars = response->variables; last_var = NULL; while (vars) { out_len = 0; sprint_realloc_objid((u_char **)&buf, &buf_len, &out_len, 1, vars->name, vars->name_length); if (vars->type == SNMP_ENDOFMIBVIEW || memcmp(vars->name, name, rootlen * sizeof(oid)) != 0) { if (localdebug) { printf("%s => end of table\n", buf ? (char *) buf : "[NIL]"); } running = 0; break; } if (localdebug) { printf("%s => taken\n", buf ? (char *) buf : "[NIL]"); } for (col = 0; col < fields; col++) if (column[col].subid == vars->name[rootlen]) break; if (col == fields) { extra_columns = 1; last_var = vars; vars = vars->next_variable; continue; } if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX)) { name_p = strchr(buf, '['); } else { switch (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)) { case NETSNMP_OID_OUTPUT_MODULE: case 0: name_p = strchr(buf, ':')+1; break; case NETSNMP_OID_OUTPUT_SUFFIX: name_p = buf; break; case NETSNMP_OID_OUTPUT_FULL: case NETSNMP_OID_OUTPUT_NUMERIC: case NETSNMP_OID_OUTPUT_UCD: name_p = buf + strlen(table_name)+1; name_p = strchr(name_p, '.')+1; break; default: fprintf(stderr, "Unrecognized -O option: %d\n", netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)); exit(1); } name_p = strchr(name_p, '.'); if ( name_p == NULL ) { /* The 'strchr' call above failed, i.e. the results * don't seem to include instance subidentifiers! */ running = 0; break; } name_p++; /* Move on to the instance identifier */ } for (row = 0; row < entries; row++) if (strcmp(name_p, indices[row]) == 0) break; if (row == entries) { entries++; if (entries >= allocated) { if (allocated == 0) { allocated = 10; data = (char **) malloc(allocated * fields * sizeof(char *)); memset(data, 0, allocated * fields * sizeof(char *)); indices = (char **) malloc(allocated * sizeof(char *)); } else { allocated += 10; data = (char **) realloc(data, allocated * fields * sizeof(char *)); memset(data + entries * fields, 0, (allocated - entries) * fields * sizeof(char *)); indices = (char **) realloc(indices, allocated * sizeof(char *)); } } indices[row] = strdup(name_p); i = strlen(name_p); if (i > index_width) index_width = i; } dp = data + row * fields; out_len = 0; sprint_realloc_value((u_char **)&buf, &buf_len, &out_len, 1, vars->name, vars->name_length, vars); for (cp = buf; *cp; cp++) if (*cp == '\n') *cp = ' '; dp[col] = buf; i = out_len; buf = NULL; buf_len = 0; if (i > column[col].width) column[col].width = i; last_var = vars; vars = vars->next_variable; } if (last_var) { name_length = last_var->name_length; memcpy(name, last_var->name, name_length * sizeof(oid)); } } else { /* * error in response, print it */ running = 0; if (response->errstat == SNMP_ERR_NOSUCHNAME) { printf("End of MIB\n"); } else { fprintf(stderr, "Error in packet.\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errstat == SNMP_ERR_NOSUCHNAME) { fprintf(stderr, "The request for this object identifier failed: "); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) /*EMPTY*/; if (vars) { fprint_objid(stderr, vars->name, vars->name_length); } fprintf(stderr, "\n"); } exitval = 2; } } } else if (status == STAT_TIMEOUT) { fprintf(stderr, "Timeout: No Response from %s\n", ss->peername); running = 0; exitval = 1; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmptable", ss); running = 0; exitval = 1; } if (response) snmp_free_pdu(response); } }
void get_table_entries(netsnmp_session * ss) { int running = 1; netsnmp_pdu *pdu, *response; netsnmp_variable_list *vars; int count; int status; int i; int col; char *buf = NULL; size_t out_len = 0, buf_len = 0; char *cp; char *name_p = NULL; char **dp; int have_current_index; /* * TODO: * 1) Deal with multiple index fields * 2) Deal with variable length index fields * 3) optimize to remove a sparse column from get-requests */ while (running && ((max_width && !column_width) || (entries < max_getbulk))) { /* * create PDU for GETNEXT request and add object name to request */ pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); for (i = 1; i <= fields; i++) { name[rootlen] = column[i - 1].subid; snmp_add_null_var(pdu, name, name_length); } /* * do the request */ status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response->errstat == SNMP_ERR_NOERROR) { /* * check resulting variables */ vars = response->variables; entries++; if (entries >= allocated) { if (allocated == 0) { allocated = 10; data = (char **) malloc(allocated * fields * sizeof(char *)); memset(data, 0, allocated * fields * sizeof(char *)); if (show_index) indices = (char **) malloc(allocated * sizeof(char *)); } else { allocated += 10; data = (char **) realloc(data, allocated * fields * sizeof(char *)); memset(data + entries * fields, 0, (allocated - entries) * fields * sizeof(char *)); if (show_index) indices = (char **) realloc(indices, allocated * sizeof(char *)); } } dp = data + (entries - 1) * fields; col = -1; end_of_table = 1; /* assume end of table */ have_current_index = 0; name_length = rootlen + 1; for (vars = response->variables; vars; vars = vars->next_variable) { col++; name[rootlen] = column[col].subid; if ((vars->name_length < name_length) || (vars->name[rootlen] != column[col].subid) || memcmp(name, vars->name, name_length * sizeof(oid)) != 0 || vars->type == SNMP_ENDOFMIBVIEW) { /* * not part of this subtree */ if (localdebug) { fprint_variable(stderr, vars->name, vars->name_length, vars); fprintf(stderr, " => ignored\n"); } continue; } /* * save index off */ if (!have_current_index) { end_of_table = 0; have_current_index = 1; name_length = vars->name_length; memcpy(name, vars->name, name_length * sizeof(oid)); out_len = 0; if (!sprint_realloc_objid ((u_char **)&buf, &buf_len, &out_len, 1, vars->name, vars->name_length)) { break; } i = vars->name_length - rootlen + 1; if (localdebug || show_index) { if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX)) { name_p = strchr(buf, '['); } else { switch (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)) { case NETSNMP_OID_OUTPUT_MODULE: case 0: name_p = strchr(buf, ':'); break; case NETSNMP_OID_OUTPUT_SUFFIX: name_p = buf; break; case NETSNMP_OID_OUTPUT_FULL: case NETSNMP_OID_OUTPUT_NUMERIC: case NETSNMP_OID_OUTPUT_UCD: name_p = buf + strlen(table_name)+1; name_p = strchr(name_p, '.')+1; break; default: fprintf(stderr, "Unrecognized -O option: %d\n", netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)); exit(1); } name_p = strchr(name_p, '.') + 1; } } if (localdebug) { printf("Name: %s Index: %s\n", buf, name_p); } if (show_index) { indices[entries - 1] = strdup(name_p); i = strlen(name_p); if (i > index_width) index_width = i; } } if (localdebug && buf) { printf("%s => taken\n", buf); } out_len = 0; sprint_realloc_value((u_char **)&buf, &buf_len, &out_len, 1, vars->name, vars->name_length, vars); for (cp = buf; *cp; cp++) { if (*cp == '\n') { *cp = ' '; } } dp[col] = buf; i = out_len; buf = NULL; buf_len = 0; if (i > column[col].width) { column[col].width = i; } } if (end_of_table) { --entries; /* * not part of this subtree */ if (localdebug) { printf("End of table: %s\n", buf ? (char *) buf : "[NIL]"); } running = 0; continue; } } else { /* * error in response, print it */ running = 0; if (response->errstat == SNMP_ERR_NOSUCHNAME) { printf("End of MIB\n"); end_of_table = 1; } else { fprintf(stderr, "Error in packet.\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errindex != 0) { fprintf(stderr, "Failed object: "); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) /*EMPTY*/; if (vars) { fprint_objid(stderr, vars->name, vars->name_length); } fprintf(stderr, "\n"); } exitval = 2; } } } else if (status == STAT_TIMEOUT) { fprintf(stderr, "Timeout: No Response from %s\n", ss->peername); running = 0; exitval = 1; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmptable", ss); running = 0; exitval = 1; } if (response) snmp_free_pdu(response); } }