/* * This routine loads MIB files, and computes the key-OID values. * We defer this until the mib-definition is actually being referred to * in snmphosts.cfg, because lots of MIB's are not being used * (and probably do not exist on the host where we're running) and * to avoid spending a lot of time to load MIB's that are not used. */ void setupmib(mibdef_t *mib, int verbose) { mibidx_t *iwalk; size_t sz, len; if (mib->loadstatus != MIB_STATUS_NOTLOADED) return; if (mib->mibfn && (read_mib(mib->mibfn) == NULL)) { mib->loadstatus = MIB_STATUS_LOADFAILED; if (verbose) { errprintf("Failed to read MIB file %s\n", mib->mibfn); snmp_perror("read_objid"); } } for (iwalk = mib->idxlist; (iwalk); iwalk = iwalk->next) { iwalk->rootoid = calloc(MAX_OID_LEN, sizeof(oid)); iwalk->rootoidlen = MAX_OID_LEN; if (read_objid(iwalk->keyoid, iwalk->rootoid, &iwalk->rootoidlen)) { /* Re-use the iwalk->keyoid buffer */ sz = strlen(iwalk->keyoid) + 1; len = 0; sprint_realloc_objid((unsigned char **)&iwalk->keyoid, &sz, &len, 1, iwalk->rootoid, iwalk->rootoidlen); } else { mib->loadstatus = MIB_STATUS_LOADFAILED; if (verbose) { errprintf("Cannot determine OID for %s\n", iwalk->keyoid); snmp_perror("read_objid"); } } } mib->loadstatus = MIB_STATUS_LOADED; }
void debugmsg_oid (const char *token, const oid * theoid, size_t len) { u_char *buf = NULL; size_t buf_len = 0, out_len = 0; if (sprint_realloc_objid (&buf, &buf_len, &out_len, 1, theoid, len)) { if (buf != NULL) { debugmsg (token, "%s", buf); } } else { if (buf != NULL) { debugmsg (token, "%s [TRUNCATED]", buf); } } if (buf != NULL) { free (buf); } }
void sprint_descriptor(char *buffer, struct varInfo *vip) { char *buf = NULL, *cp = NULL; size_t buf_len = 0, out_len = 0; if (!sprint_realloc_objid((u_char **)&buf, &buf_len, &out_len, 1, vip->info_oid, vip->oidlen)) { if (buf != NULL) { free(buf); } return; } for (cp = buf; *cp; cp++); while (cp >= buf) { if (isalpha((unsigned char)(*cp))) break; cp--; } while (cp >= buf) { if (*cp == '.') break; cp--; } cp++; if (cp < buf) cp = buf; strcpy(buffer, cp); if (buf != NULL) { free(buf); } }
void debugmsg_oidrange (const char *token, const oid * theoid, size_t len, size_t var_subid, oid range_ubound) { u_char *buf = NULL; size_t buf_len = 0, out_len = 0, i = 0; int rc = 0; if (var_subid == 0) { rc = sprint_realloc_objid (&buf, &buf_len, &out_len, 1, theoid, len); } else { char tmpbuf[128]; /* XXX - ? check for 0 == var_subid -1 ? */ rc = sprint_realloc_objid (&buf, &buf_len, &out_len, 1, theoid, var_subid - 1); /* Adjust for C's 0-based array indexing */ if (rc) { sprintf (tmpbuf, ".%" NETSNMP_PRIo "u--%" NETSNMP_PRIo "u", theoid[var_subid - 1], range_ubound); rc = snmp_cstrcat (&buf, &buf_len, &out_len, 1, tmpbuf); if (rc) { for (i = var_subid; i < len; i++) { sprintf (tmpbuf, ".%" NETSNMP_PRIo "u", theoid[i]); if (!snmp_cstrcat (&buf, &buf_len, &out_len, 1, tmpbuf)) { break; } } } } } if (buf != NULL) { debugmsg (token, "%s%s", buf, rc ? "" : " [TRUNCATED]"); free (buf); } }
/** frees a cache */ int netsnmp_cache_free(netsnmp_cache *cache) { netsnmp_cache *pos; if (NULL == cache) return SNMPERR_SUCCESS; for (pos = cache_head; pos; pos = pos->next) { if (pos == cache) { size_t out_len = 0; size_t buf_len = 0; char *buf = NULL; sprint_realloc_objid((u_char **) &buf, &buf_len, &out_len, 1, pos->rootoid, pos->rootoid_len); snmp_log(LOG_WARNING, "not freeing cache with root OID %s (still in list)\n", buf); free(buf); return SNMP_ERR_GENERR; } } if(0 != cache->timer_id) netsnmp_cache_timer_stop(cache); if (cache->valid) _cache_free(cache); if (cache->timestampM) free(cache->timestampM); if (cache->rootoid) free(cache->rootoid); free(cache); return SNMPERR_SUCCESS; }
/* * 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 dump_idx_registry(void) { struct snmp_index *idxptr, *idxptr2; u_char *sbuf = NULL, *ebuf = NULL; size_t sbuf_len = 0, sout_len = 0, ebuf_len = 0, eout_len = 0; if (snmp_index_head != NULL) { printf("\nIndex Allocations:\n"); } for (idxptr = snmp_index_head; idxptr != NULL; idxptr = idxptr->next_oid) { sout_len = 0; if (sprint_realloc_objid(&sbuf, &sbuf_len, &sout_len, 1, idxptr->varbind->name, idxptr->varbind->name_length)) { printf("%s indexes:\n", sbuf); } else { printf("%s [TRUNCATED] indexes:\n", sbuf); } for (idxptr2 = idxptr; idxptr2 != NULL; idxptr2 = idxptr2->next_idx) { switch (idxptr2->varbind->type) { case ASN_INTEGER: printf(" %ld for session %8p, allocated %d\n", *idxptr2->varbind->val.integer, idxptr2->session, idxptr2->allocated); break; case ASN_OCTET_STR: printf(" \"%s\" for session %8p, allocated %d\n", idxptr2->varbind->val.string, idxptr2->session, idxptr2->allocated); break; case ASN_OBJECT_ID: eout_len = 0; if (sprint_realloc_objid(&ebuf, &ebuf_len, &eout_len, 1, idxptr2->varbind->val.objid, idxptr2->varbind->val_len / sizeof(oid))) { printf(" %s for session %8p, allocated %d\n", ebuf, idxptr2->session, idxptr2->allocated); } else { printf (" %s [TRUNCATED] for sess %8p, allocated %d\n", ebuf, idxptr2->session, idxptr2->allocated); } break; default: printf("unsupported type (%d/0x%02x)\n", idxptr2->varbind->type, idxptr2->varbind->type); } } } if (sbuf != NULL) { free(sbuf); } if (ebuf != NULL) { free(ebuf); } }
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); } }
void get_field_names(void) { char *buf = NULL, *name_p = NULL; size_t buf_len = 0, out_len = 0; #ifndef NETSNMP_DISABLE_MIB_LOADING struct tree *tbl = NULL; #endif /* NETSNMP_DISABLE_MIB_LOADING */ int going = 1; #ifndef NETSNMP_DISABLE_MIB_LOADING tbl = get_tree(root, rootlen, get_tree_head()); if (tbl) { tbl = tbl->child_list; if (tbl) { root[rootlen++] = tbl->subid; tbl = tbl->child_list; } else { root[rootlen++] = 1; going = 0; } } #endif /* NETSNMP_DISABLE_MIB_LOADING */ if (sprint_realloc_objid ((u_char **)&buf, &buf_len, &out_len, 1, root, rootlen - 1)) { table_name = buf; buf = NULL; buf_len = out_len = 0; } else { table_name = strdup("[TRUNCATED]"); out_len = 0; } fields = 0; while (going) { fields++; #ifndef NETSNMP_DISABLE_MIB_LOADING if (tbl) { if (tbl->access == MIB_ACCESS_NOACCESS) { fields--; tbl = tbl->next_peer; if (!tbl) { going = 0; } continue; } root[rootlen] = tbl->subid; tbl = tbl->next_peer; if (!tbl) going = 0; } else { #endif /* NETSNMP_DISABLE_MIB_LOADING */ root[rootlen] = fields; #ifndef NETSNMP_DISABLE_MIB_LOADING } #endif /* NETSNMP_DISABLE_MIB_LOADING */ out_len = 0; if (sprint_realloc_objid ((u_char **)&buf, &buf_len, &out_len, 1, root, rootlen + 1)) { name_p = strrchr(buf, '.'); if (name_p == NULL) { name_p = strrchr(buf, ':'); } if (name_p == NULL) { name_p = buf; } else { name_p++; } } else { break; } if (localdebug) { printf("%s %c\n", buf, name_p[0]); } if ('0' <= name_p[0] && name_p[0] <= '9') { fields--; break; } if (fields == 1) { column = (struct column *) malloc(sizeof(*column)); } else { column = (struct column *) realloc(column, fields * sizeof(*column)); } column[fields - 1].label = strdup(name_p); column[fields - 1].width = strlen(name_p); column[fields - 1].subid = root[rootlen]; } if (fields == 0) { fprintf(stderr, "Was that a table? %s\n", table_name); exit(1); } if (name_p) { *name_p = 0; memmove(name, root, rootlen * sizeof(oid)); name_length = rootlen + 1; name_p = strrchr(buf, '.'); if (name_p == NULL) { name_p = strrchr(buf, ':'); } if (name_p != NULL) { *name_p = 0; } } if (brief && fields > 1) { char *f1, *f2; int common = strlen(column[0].label); int field, len; for (field = 1; field < fields; field++) { f1 = column[field - 1].label; f2 = column[field].label; while (*f1 && *f1++ == *f2++); len = f2 - column[field].label - 1; if (len < common) common = len; } if (common) { for (field = 0; field < fields; field++) { column[field].label += common; column[field].width -= common; } } } if (buf != NULL) { free(buf); } }