char * get_FilterProfileName(const char *paramName, size_t paramName_len, size_t * profileName_len) { netsnmp_variable_list *vars = NULL; struct snmpNotifyFilterProfileTable_data *data; /* * put requested info into var structure */ snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OCTET_STR, (const u_char *) paramName, paramName_len); /* * get the data from the header_complex storage */ data = (struct snmpNotifyFilterProfileTable_data *) header_complex_get(snmpNotifyFilterProfileTableStorage, vars); /* * free search index */ snmp_free_var(vars); /* * return the requested information (if this row is active) */ if (data && data->snmpNotifyFilterProfileRowStatus == RS_ACTIVE) { *profileName_len = data->snmpNotifyFilterProfileNameLen; return data->snmpNotifyFilterProfileName; } *profileName_len = 0; return NULL; }
/* * Dump IP statistics structure. */ void ip_stats(void) { oid varname[MAX_OID_LEN], *ipentry; int varname_len; netsnmp_variable_list *var; int count; struct stat_table *sp = ip_stattab; memmove(varname, oid_ipstats, sizeof(oid_ipstats)); varname_len = sizeof(oid_ipstats) / sizeof(oid); ipentry = varname + 7; printf("ip:\n"); count = sizeof(ip_stattab) / sizeof(struct stat_table); while (count--) { *ipentry = sp->entry; var = getvarbyname(Session, varname, varname_len); if (var && var->val.integer) { putchar('\t'); printf(sp->description, *var->val.integer, plural((int) *var->val.integer)); putchar('\n'); } if (var) snmp_free_var(var); sp++; } }
void _dump_stats( const char *name, oid *oid_buf, size_t buf_len, struct stat_table *stable ) { netsnmp_variable_list *var, *vp; struct stat_table *sp; oid stat; var = NULL; for (sp=stable; sp->entry; sp++) { oid_buf[buf_len-2] = sp->entry; snmp_varlist_add_variable( &var, oid_buf, buf_len, ASN_NULL, NULL, 0); } if (netsnmp_query_get( var, ss ) != SNMP_ERR_NOERROR) { /* Need to fix and re-try SNMPv1 errors */ snmp_free_var( var ); return; } printf("%s:\n", name); sp=stable; for (vp=var; vp; vp=vp->next_variable, sp++) { /* * Match the returned results against * the original stats table. */ stat = vp->name[buf_len-2]; while (sp->entry < stat) { sp++; if (sp->entry == 0) break; } if (sp->entry > stat) continue; /* Skip exceptions or missing values */ if ( !vp->val.integer ) continue; /* * If '-Cs' was specified twice, * then only display non-zero stats. */ if ( *vp->val.integer > 0 || sflag == 1 ) { putchar('\t'); printf(sp->description, *vp->val.integer, plural(*vp->val.integer)); putchar('\n'); } } snmp_free_varbind( var ); }
/* implements the table_iterator helper */ int netsnmp_table_iterator_helper_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_table_registration_info *tbl_info; netsnmp_table_request_info *table_info = NULL; oid coloid[MAX_OID_LEN]; size_t coloid_len; int ret; static oid myname[MAX_OID_LEN]; size_t myname_len; int oldmode = 0; netsnmp_iterator_info *iinfo; int notdone; netsnmp_request_info *request, *reqtmp = NULL; netsnmp_variable_list *index_search = NULL; netsnmp_variable_list *free_this_index_search = NULL; void *callback_loop_context = NULL, *last_loop_context; void *callback_data_context = NULL; ti_cache_info *ti_info = NULL; int request_count = 0; netsnmp_oid_stash_node **cinfo = NULL; netsnmp_variable_list *old_indexes = NULL, *vb; netsnmp_table_registration_info *table_reg_info = NULL; int i; netsnmp_data_list *ldata = NULL; iinfo = (netsnmp_iterator_info *) handler->myvoid; if (!iinfo || !reginfo || !reqinfo) return SNMPERR_GENERR; tbl_info = iinfo->table_reginfo; /* * copy in the table registration oid for later use */ coloid_len = reginfo->rootoid_len + 2; memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid)); coloid[reginfo->rootoid_len] = 1; /* table.entry node */ /* * illegally got here if these functions aren't defined */ if (iinfo->get_first_data_point == NULL || iinfo->get_next_data_point == NULL) { snmp_log(LOG_ERR, "table_iterator helper called without data accessor functions\n"); return SNMP_ERR_GENERR; } /* preliminary analysis */ switch (reqinfo->mode) { case MODE_GET_STASH: cinfo = netsnmp_extract_stash_cache(reqinfo); table_reg_info = netsnmp_find_table_registration_info(reginfo); /* XXX: move this malloc to stash_cache handler? */ reqtmp = SNMP_MALLOC_TYPEDEF(netsnmp_request_info); reqtmp->subtree = requests->subtree; table_info = netsnmp_extract_table_info(requests); netsnmp_request_add_list_data(reqtmp, netsnmp_create_data_list (TABLE_HANDLER_NAME, (void *) table_info, NULL)); /* remember the indexes that were originally parsed. */ old_indexes = table_info->indexes; break; case MODE_GETNEXT: for(request = requests ; request; request = request->next) { if (request->processed) continue; table_info = netsnmp_extract_table_info(request); if (table_info->colnum < tbl_info->min_column - 1) { /* XXX: optimize better than this */ /* for now, just increase to colnum-1 */ /* we need to jump to the lowest result of the min_column and take it, comparing to nothing from the request */ table_info->colnum = tbl_info->min_column - 1; } else if (table_info->colnum > tbl_info->max_column) { request->processed = TABLE_ITERATOR_NOTAGAIN; } ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); if (!ti_info) { ti_info = SNMP_MALLOC_TYPEDEF(ti_cache_info); netsnmp_request_add_list_data(request, netsnmp_create_data_list (TI_REQUEST_CACHE, ti_info, netsnmp_free_ti_cache)); } /* XXX: if no valid requests, don't even loop below */ } break; } /* * collect all information for each needed row */ if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GET_STASH || reqinfo->mode == MODE_SET_RESERVE1) { /* * Count the number of request in the list, * so that we'll know when we're finished */ for(request = requests ; request; request = request->next) if (!request->processed) request_count++; notdone = 1; while(notdone) { notdone = 0; /* find first data point */ if (!index_search) { if (free_this_index_search) { /* previously done */ index_search = free_this_index_search; } else { for(request=requests ; request; request=request->next) { table_info = netsnmp_extract_table_info(request); if (table_info) break; } if (!table_info) { snmp_log(LOG_WARNING, "no valid requests for iterator table %s\n", reginfo->handlerName); netsnmp_free_request_data_sets(reqtmp); SNMP_FREE(reqtmp); return SNMP_ERR_NOERROR; } index_search = snmp_clone_varbind(table_info->indexes); free_this_index_search = index_search; /* setup, malloc search data: */ if (!index_search) { /* * hmmm.... invalid table? */ snmp_log(LOG_WARNING, "invalid index list or failed malloc for table %s\n", reginfo->handlerName); netsnmp_free_request_data_sets(reqtmp); SNMP_FREE(reqtmp); return SNMP_ERR_NOERROR; } } } /* if sorted, pass in a hint */ if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) { callback_loop_context = table_info; } index_search = (iinfo->get_first_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); /* loop over each data point */ while(index_search) { /* remember to free this later */ free_this_index_search = index_search; /* compare against each request*/ for(request = requests ; request; request = request->next) { if (request->processed) continue; /* XXX: store in an array for faster retrival */ table_info = netsnmp_extract_table_info(request); coloid[reginfo->rootoid_len + 1] = table_info->colnum; ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); switch(reqinfo->mode) { case MODE_GET: case MODE_SET_RESERVE1: /* looking for exact matches */ build_oid_noalloc(myname, MAX_OID_LEN, &myname_len, coloid, coloid_len, index_search); if (snmp_oid_compare(myname, myname_len, request->requestvb->name, request->requestvb->name_length) == 0) { /* keep this */ netsnmp_iterator_remember(request, myname, myname_len, callback_data_context, callback_loop_context, iinfo); request_count--; /* One less to look for */ } else { if (iinfo->free_data_context && callback_data_context) { (iinfo->free_data_context)(callback_data_context, iinfo); } } break; case MODE_GET_STASH: /* collect data for each column for every row */ build_oid_noalloc(myname, MAX_OID_LEN, &myname_len, coloid, coloid_len, index_search); reqinfo->mode = MODE_GET; if (reqtmp) ldata = netsnmp_get_list_node(reqtmp->parent_data, TABLE_ITERATOR_NAME); if (!ldata) { netsnmp_request_add_list_data(reqtmp, netsnmp_create_data_list (TABLE_ITERATOR_NAME, callback_data_context, NULL)); } else { /* may have changed */ ldata->data = callback_data_context; } table_info->indexes = index_search; for(i = table_reg_info->min_column; i <= (int)table_reg_info->max_column; i++) { myname[reginfo->rootoid_len + 1] = i; table_info->colnum = i; vb = reqtmp->requestvb = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list); vb->type = ASN_NULL; snmp_set_var_objid(vb, myname, myname_len); netsnmp_call_next_handler(handler, reginfo, reqinfo, reqtmp); reqtmp->requestvb = NULL; reqtmp->processed = 0; if (vb->type != ASN_NULL) { /* XXX, not all */ netsnmp_oid_stash_add_data(cinfo, myname, myname_len, vb); } else { snmp_free_var(vb); } } reqinfo->mode = MODE_GET_STASH; break; case MODE_GETNEXT: /* looking for "next" matches */ if (netsnmp_check_getnext_reply (request, coloid, coloid_len, index_search, &ti_info->results)) { netsnmp_iterator_remember(request, ti_info->results->name, ti_info->results->name_length, callback_data_context, callback_loop_context, iinfo); /* * If we've been told that the rows are sorted, * then the first valid one we find * must be the right one. */ if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) request_count--; } else { if (iinfo->free_data_context && callback_data_context) { (iinfo->free_data_context)(callback_data_context, iinfo); } } break; case MODE_SET_RESERVE2: case MODE_SET_FREE: case MODE_SET_UNDO: case MODE_SET_COMMIT: /* needed processing already done in RESERVE1 */ break; default: snmp_log(LOG_ERR, "table_iterator called with unsupported mode\n"); break; /* XXX return */ } } /* Is there any point in carrying on? */ if (!request_count) break; /* get the next search possibility */ last_loop_context = callback_loop_context; index_search = (iinfo->get_next_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); if (iinfo->free_loop_context && last_loop_context && callback_data_context != last_loop_context) { (iinfo->free_loop_context) (last_loop_context, iinfo); last_loop_context = NULL; } } /* free loop context before going on */ if (callback_loop_context && iinfo->free_loop_context_at_end) { (iinfo->free_loop_context_at_end) (callback_loop_context, iinfo); callback_loop_context = NULL; } /* decide which (GETNEXT) requests are not yet filled */ if (reqinfo->mode == MODE_GETNEXT) { for(request = requests ; request; request = request->next) { if (request->processed) continue; ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); if (!ti_info->results) { int nc; table_info = netsnmp_extract_table_info(request); nc = netsnmp_table_next_column(table_info); if (0 == nc) { coloid[reginfo->rootoid_len+1] = table_info->colnum+1; snmp_set_var_objid(request->requestvb, coloid, reginfo->rootoid_len+2); request->processed = TABLE_ITERATOR_NOTAGAIN; break; } else { table_info->colnum = nc; notdone = 1; } } } } } } if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_SET_RESERVE1) { /* per request last minute processing */ for(request = requests ; request; request = request->next) { if (request->processed) continue; ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); table_info = netsnmp_extract_table_info(request); if (!ti_info) continue; switch(reqinfo->mode) { case MODE_GETNEXT: if (ti_info->best_match_len) snmp_set_var_objid(request->requestvb, ti_info->best_match, ti_info->best_match_len); else { coloid[reginfo->rootoid_len+1] = netsnmp_table_next_column(table_info); if (0 == coloid[reginfo->rootoid_len+1]) { /* out of range. */ coloid[reginfo->rootoid_len+1] = tbl_info->max_column + 1; request->processed = TABLE_ITERATOR_NOTAGAIN; } snmp_set_var_objid(request->requestvb, coloid, reginfo->rootoid_len+2); request->processed = 1; } snmp_free_varbind(table_info->indexes); table_info->indexes = snmp_clone_varbind(ti_info->results); /* FALL THROUGH */ case MODE_GET: case MODE_SET_RESERVE1: if (ti_info->data_context) /* we don't add a free pointer, since it's in the TI_REQUEST_CACHE instead */ netsnmp_request_add_list_data(request, netsnmp_create_data_list (TABLE_ITERATOR_NAME, ti_info->data_context, NULL)); break; default: break; } } /* we change all GETNEXT operations into GET operations. why? because we're just so nice to the lower levels. maybe someday they'll pay us for it. doubtful though. */ oldmode = reqinfo->mode; if (reqinfo->mode == MODE_GETNEXT) { reqinfo->mode = MODE_GET; } } else if (reqinfo->mode == MODE_GET_STASH) { netsnmp_free_request_data_sets(reqtmp); SNMP_FREE(reqtmp); table_info->indexes = old_indexes; } /* Finally, we get to call the next handler below us. Boy, wasn't all that simple? They better be glad they don't have to do it! */ if (reqinfo->mode != MODE_GET_STASH) { DEBUGMSGTL(("table_iterator", "call subhandler for mode: %s\n", se_find_label_in_slist("agent_mode", oldmode))); ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); } /* reverse the previously saved mode if we were a getnext */ if (oldmode == MODE_GETNEXT) { reqinfo->mode = oldmode; } /* cleanup */ if (free_this_index_search) snmp_free_varbind(free_this_index_search); return SNMP_ERR_NOERROR; }
int write_snmpNotifyRowStatus(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, u_char * statP, oid * name, size_t name_len) { struct snmpNotifyTable_data *StorageTmp = NULL; static struct snmpNotifyTable_data *StorageDel; size_t newlen = name_len - (sizeof(snmpNotifyTable_variables_oid) / sizeof(oid) + 3 - 1); static int old_value; int set_value = *((long *) var_val); static netsnmp_variable_list *vars, *vp; struct header_complex_index *hciptr; DEBUGMSGTL(("snmpNotifyTable", "write_snmpNotifyRowStatus entering action=%d... \n", action)); StorageTmp = (struct snmpNotifyTable_data *) header_complex((struct header_complex_index *) snmpNotifyTableStorage, NULL, &name[sizeof(snmpNotifyTable_variables_oid) / sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL); switch (action) { case RESERVE1: if (var_val_type != ASN_INTEGER || var_val == NULL) { return SNMP_ERR_WRONGTYPE; } if (var_val_len != sizeof(long)) { return SNMP_ERR_WRONGLENGTH; } if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY) { return SNMP_ERR_WRONGVALUE; } if (StorageTmp == NULL) { /* * create the row now? */ /* * ditch illegal values now */ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) { return SNMP_ERR_INCONSISTENTVALUE; } } else { /* * row exists. Check for a valid state change */ if (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT) { /* * can't create a row that exists */ return SNMP_ERR_INCONSISTENTVALUE; } /* * XXX: interaction with row storage type needed */ } /* * memory reseveration, final preparation... */ if (StorageTmp == NULL && (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT)) { /* * creation */ vars = NULL; snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OCTET_STR, NULL, 0); /* snmpNotifyName */ if (header_complex_parse_oid (& (name [sizeof(snmpNotifyTable_variables_oid) / sizeof(oid) + 2]), newlen, vars) != SNMPERR_SUCCESS) { /* * XXX: free, zero vars */ snmp_free_var(vars); return SNMP_ERR_INCONSISTENTNAME; } vp = vars; StorageNew = SNMP_MALLOC_STRUCT(snmpNotifyTable_data); if (StorageNew == NULL) { return SNMP_ERR_RESOURCEUNAVAILABLE; } memdup((u_char **) & (StorageNew->snmpNotifyName), vp->val.string, vp->val_len); if (StorageNew->snmpNotifyName == NULL) { return SNMP_ERR_RESOURCEUNAVAILABLE; } StorageNew->snmpNotifyNameLen = vp->val_len; vp = vp->next_variable; /* * default values */ StorageNew->snmpNotifyStorageType = ST_NONVOLATILE; StorageNew->snmpNotifyType = SNMPNOTIFYTYPE_TRAP; StorageNew->snmpNotifyTagLen = 0; StorageNew->snmpNotifyTag = (char *) calloc(sizeof(char), 1); if (StorageNew->snmpNotifyTag == NULL) { return SNMP_ERR_RESOURCEUNAVAILABLE; } StorageNew->snmpNotifyRowStatus = set_value; snmp_free_var(vars); } break; case RESERVE2: break; case FREE: if (StorageNew != NULL) { SNMP_FREE(StorageNew->snmpNotifyTag); SNMP_FREE(StorageNew->snmpNotifyName); free(StorageNew); StorageNew = NULL; } break; case ACTION: if (StorageTmp == NULL && (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT)) { /* * row creation, so add it */ if (StorageNew != NULL) { snmpNotifyTable_add(StorageNew); } } else if (set_value != RS_DESTROY) { /* * set the flag? */ old_value = StorageTmp->snmpNotifyRowStatus; StorageTmp->snmpNotifyRowStatus = *((long *) var_val); } else { /* * destroy... extract it for now */ if (StorageTmp) { hciptr = header_complex_find_entry(snmpNotifyTableStorage, StorageTmp); StorageDel = (struct snmpNotifyTable_data *) header_complex_extract_entry((struct header_complex_index **) &snmpNotifyTableStorage, hciptr); } } break; case UNDO: /* * Back out any changes made in the ACTION case */ if (StorageTmp == NULL && (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT)) { /* * row creation, so remove it again */ hciptr = header_complex_find_entry(snmpNotifyTableStorage, StorageNew); StorageDel = (struct snmpNotifyTable_data *) header_complex_extract_entry((struct header_complex_index **) &snmpNotifyTableStorage, hciptr); /* * XXX: free it */ } else if (StorageDel != NULL) { /* * row deletion, so add it again */ snmpNotifyTable_add(StorageDel); } else if (set_value != RS_DESTROY) { StorageTmp->snmpNotifyRowStatus = old_value; } break; case COMMIT: if (StorageDel != NULL) { SNMP_FREE(StorageDel->snmpNotifyTag); SNMP_FREE(StorageDel->snmpNotifyName); free(StorageDel); StorageDel = NULL; } if (StorageTmp && StorageTmp->snmpNotifyRowStatus == RS_CREATEANDGO) { StorageTmp->snmpNotifyRowStatus = RS_ACTIVE; StorageNew = NULL; } else if (StorageTmp && StorageTmp->snmpNotifyRowStatus == RS_CREATEANDWAIT) { StorageTmp->snmpNotifyRowStatus = RS_NOTINSERVICE; StorageNew = NULL; } break; } return SNMP_ERR_NOERROR; }
int unregister_index(netsnmp_variable_list * varbind, int remember, netsnmp_session * ss) { struct snmp_index *idxptr, *idxptr2; struct snmp_index *prev_oid_ptr, *prev_idx_ptr; int res, res2, i; #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING) if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) { return (agentx_unregister_index(ss, varbind)); } #endif /* * Look for the requested OID entry */ prev_oid_ptr = NULL; prev_idx_ptr = NULL; res = 1; res2 = 1; for (idxptr = snmp_index_head; idxptr != NULL; prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) { if ((res = snmp_oid_compare(varbind->name, varbind->name_length, idxptr->varbind->name, idxptr->varbind->name_length)) <= 0) break; } if (res != 0) return INDEX_ERR_NOT_ALLOCATED; if (varbind->type != idxptr->varbind->type) return INDEX_ERR_WRONG_TYPE; for (idxptr2 = idxptr; idxptr2 != NULL; prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { switch (varbind->type) { case ASN_INTEGER: res2 = (*varbind->val.integer - *idxptr2->varbind->val.integer); break; case ASN_OCTET_STR: i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len); res2 = memcmp(varbind->val.string, idxptr2->varbind->val.string, i); break; case ASN_OBJECT_ID: res2 = snmp_oid_compare(varbind->val.objid, varbind->val_len / sizeof(oid), idxptr2->varbind->val.objid, idxptr2->varbind->val_len / sizeof(oid)); break; default: return INDEX_ERR_WRONG_TYPE; /* wrong type */ } if (res2 <= 0) break; } if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) { return INDEX_ERR_NOT_ALLOCATED; } if (ss != idxptr2->session) return INDEX_ERR_WRONG_SESSION; /* * If this is a "normal" index unregistration, * mark the index entry as unused, but leave * it in situ. This allows differentiation * between ANY_INDEX and NEW_INDEX */ if (remember) { idxptr2->allocated = 0; /* Unused index */ idxptr2->session = NULL; return SNMP_ERR_NOERROR; } /* * If this is a failed attempt to register a * number of indexes, the successful ones * must be removed completely. */ if (prev_idx_ptr) { prev_idx_ptr->next_idx = idxptr2->next_idx; } else if (prev_oid_ptr) { if (idxptr2->next_idx) /* Use p_idx_ptr as a temp variable */ prev_idx_ptr = idxptr2->next_idx; else prev_idx_ptr = idxptr2->next_oid; while (prev_oid_ptr) { prev_oid_ptr->next_oid = prev_idx_ptr; prev_oid_ptr = prev_oid_ptr->next_idx; } } else { if (idxptr2->next_idx) snmp_index_head = idxptr2->next_idx; else snmp_index_head = idxptr2->next_oid; } snmp_free_var(idxptr2->varbind); free(idxptr2); return SNMP_ERR_NOERROR; }
netsnmp_variable_list * register_index(netsnmp_variable_list * varbind, int flags, netsnmp_session * ss) { netsnmp_variable_list *rv = NULL; struct snmp_index *new_index, *idxptr, *idxptr2; struct snmp_index *prev_oid_ptr, *prev_idx_ptr; int res, res2, i; DEBUGMSGTL(("register_index", "register ")); DEBUGMSGVAR(("register_index", varbind)); DEBUGMSG(("register_index", "for session %8p\n", ss)); #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING) if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) { return (agentx_register_index(ss, varbind, flags)); } #endif /* * Look for the requested OID entry */ prev_oid_ptr = NULL; prev_idx_ptr = NULL; res = 1; res2 = 1; for (idxptr = snmp_index_head; idxptr != NULL; prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) { if ((res = snmp_oid_compare(varbind->name, varbind->name_length, idxptr->varbind->name, idxptr->varbind->name_length)) <= 0) break; } /* * Found the OID - now look at the registered indices */ if (res == 0 && idxptr) { if (varbind->type != idxptr->varbind->type) return NULL; /* wrong type */ /* * If we've been asked for an arbitrary new value, * then find the end of the list. * If we've been asked for any arbitrary value, * then look for an unused entry, and use that. * If there aren't any, continue as for new. * Otherwise, locate the given value in the (sorted) * list of already allocated values */ if (flags & ALLOCATE_ANY_INDEX) { for (idxptr2 = idxptr; idxptr2 != NULL; prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) { if ((rv = snmp_clone_varbind(idxptr2->varbind)) != NULL) { idxptr2->session = ss; idxptr2->allocated = 1; } return rv; } } } else { for (idxptr2 = idxptr; idxptr2 != NULL; prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { switch (varbind->type) { case ASN_INTEGER: res2 = (*varbind->val.integer - *idxptr2->varbind->val.integer); break; case ASN_OCTET_STR: i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len); res2 = memcmp(varbind->val.string, idxptr2->varbind->val.string, i); break; case ASN_OBJECT_ID: res2 = snmp_oid_compare(varbind->val.objid, varbind->val_len / sizeof(oid), idxptr2->varbind->val.objid, idxptr2->varbind->val_len / sizeof(oid)); break; default: return NULL; /* wrong type */ } if (res2 <= 0) break; } if (res2 == 0) { if (idxptr2->allocated) { /* * No good: the index is in use. */ return NULL; } else { /* * Okay, it's unallocated, we can just claim ownership * here. */ if ((rv = snmp_clone_varbind(idxptr2->varbind)) != NULL) { idxptr2->session = ss; idxptr2->allocated = 1; } return rv; } } } } /* * OK - we've now located where the new entry needs to * be fitted into the index registry tree * To recap: * 'prev_oid_ptr' points to the head of the OID index * list prior to this one. If this is null, then * it means that this is the first OID in the list. * 'idxptr' points either to the head of this OID list, * or the next OID (if this is a new OID request) * These can be distinguished by the value of 'res'. * * 'prev_idx_ptr' points to the index entry that sorts * immediately prior to the requested value (if any). * If an arbitrary value is required, then this will * point to the last allocated index. * If this pointer is null, then either this is a new * OID request, or the requested value is the first * in the list. * 'idxptr2' points to the next sorted index (if any) * but is not actually needed any more. * * Clear? Good! * I hope you've been paying attention. * There'll be a test later :-) */ /* * We proceed by creating the new entry * (by copying the entry provided) */ new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index)); if (new_index == NULL) return NULL; if (NULL == snmp_varlist_add_variable(&new_index->varbind, varbind->name, varbind->name_length, varbind->type, varbind->val.string, varbind->val_len)) { /* * if (snmp_clone_var( varbind, new_index->varbind ) != 0 ) */ free(new_index); return NULL; } new_index->session = ss; new_index->allocated = 1; if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX) new_index->varbind->val.string[new_index->varbind->val_len] = 0; /* * If we've been given a value, then we can use that, but * otherwise, we need to create a new value for this entry. * Note that ANY_INDEX and NEW_INDEX are both covered by this * test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?) */ if (flags & ALLOCATE_ANY_INDEX) { if (prev_idx_ptr) { if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind) != 0) { free(new_index); return NULL; } } else new_index->varbind->val.string = new_index->varbind->buf; switch (varbind->type) { case ASN_INTEGER: if (prev_idx_ptr) { (*new_index->varbind->val.integer)++; } else *(new_index->varbind->val.integer) = 1; new_index->varbind->val_len = sizeof(long); break; case ASN_OCTET_STR: if (prev_idx_ptr) { i = new_index->varbind->val_len - 1; while (new_index->varbind->buf[i] == 'z') { new_index->varbind->buf[i] = 'a'; i--; if (i < 0) { i = new_index->varbind->val_len; new_index->varbind->buf[i] = 'a'; new_index->varbind->buf[i + 1] = 0; } } new_index->varbind->buf[i]++; } else strcpy((char *) new_index->varbind->buf, "aaaa"); new_index->varbind->val_len = strlen((char *) new_index->varbind->buf); break; case ASN_OBJECT_ID: if (prev_idx_ptr) { i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1; while (new_index->varbind->val.objid[i] == 255) { new_index->varbind->val.objid[i] = 1; i--; if (i == 0 && new_index->varbind->val.objid[0] == 2) { new_index->varbind->val.objid[0] = 1; i = new_index->varbind->val_len / sizeof(oid); new_index->varbind->val.objid[i] = 0; new_index->varbind->val_len += sizeof(oid); } } new_index->varbind->val.objid[i]++; } else { /* * If the requested OID name is small enough, * * append another OID (1) and use this as the * * default starting value for new indexes. */ if ((varbind->name_length + 1) * sizeof(oid) <= 40) { for (i = 0; i < (int) varbind->name_length; i++) new_index->varbind->val.objid[i] = varbind->name[i]; new_index->varbind->val.objid[varbind->name_length] = 1; new_index->varbind->val_len = (varbind->name_length + 1) * sizeof(oid); } else { /* * Otherwise use '.1.1.1.1...' */ i = 40 / sizeof(oid); if (i > 4) i = 4; new_index->varbind->val_len = i * (sizeof(oid)); for (i--; i >= 0; i--) new_index->varbind->val.objid[i] = 1; } } break; default: snmp_free_var(new_index->varbind); free(new_index); return NULL; /* Index type not supported */ } } /* * Try to duplicate the new varbind for return. */ if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) { snmp_free_var(new_index->varbind); free(new_index); return NULL; } /* * Right - we've set up the new entry. * All that remains is to link it into the tree. * There are a number of possible cases here, * so watch carefully. */ if (prev_idx_ptr) { new_index->next_idx = prev_idx_ptr->next_idx; new_index->next_oid = prev_idx_ptr->next_oid; prev_idx_ptr->next_idx = new_index; } else { if (res == 0 && idxptr) { new_index->next_idx = idxptr; new_index->next_oid = idxptr->next_oid; } else { new_index->next_idx = NULL; new_index->next_oid = idxptr; } if (prev_oid_ptr) { while (prev_oid_ptr) { prev_oid_ptr->next_oid = new_index; prev_oid_ptr = prev_oid_ptr->next_idx; } } else snmp_index_head = new_index; } return rv; }
/* * Print a running summary of interface statistics. * Repeat display every interval seconds, showing statistics * collected over that interval. Assumes that interval is non-zero. * First line printed at top of screen is always cumulative. */ static void sidewaysintpr(unsigned int interval) { register struct iftot *ip, *total; register int line; struct iftot *lastif, *sum, *interesting, ifnow, *now = &ifnow; struct variable_list *var; oid varname[MAX_OID_LEN], *instance, *ifentry; size_t varname_len; int ifnum, cfg_nnets; lastif = iftot; sum = iftot + MAXIF - 1; total = sum - 1; interesting = iftot; var = getvarbyname(Session, oid_cfg_nnets, sizeof(oid_cfg_nnets) / sizeof(oid)); if (var) { cfg_nnets = *var->val.integer; snmp_free_var(var); } else return; memmove(varname, oid_ifname, sizeof(oid_ifname)); varname_len = sizeof(oid_ifname) / sizeof(oid); for (ifnum = 1, ip = iftot; ifnum <= cfg_nnets; ifnum++) { char *cp; ip->ift_name[0] = '('; varname[10] = ifnum; var = getvarbyname(Session, varname, varname_len); if (var){ if (var->val_len >= (sizeof(ip->ift_name) - 3)) var->val_len = (sizeof(ip->ift_name) - 4); memmove(ip->ift_name + 1, var->val.string, var->val_len); snmp_free_var(var); } cp = (char *) strchr(ip->ift_name, ' '); if ( cp != NULL ) *cp = '\0'; if (intrface && strcmp(ip->ift_name + 1, intrface) == 0) interesting = ip; ip->ift_name[15] = '\0'; cp = (char *) strchr(ip->ift_name, '\0'); sprintf(cp, ")"); ip++; if (ip >= iftot + MAXIF - 2) break; } lastif = ip; timerSet(interval); banner: printf(" input %-6.6s output ", interesting->ift_name); if (lastif - iftot > 0) printf(" input (Total) output"); for (ip = iftot; ip < iftot + MAXIF; ip++) { ip->ift_ip = 0; ip->ift_ie = 0; ip->ift_op = 0; ip->ift_oe = 0; ip->ift_co = 0; } putchar('\n'); printf("%10.10s %8.8s %10.10s %8.8s %8.8s ", "packets", "errs", "packets", "errs", "colls"); if (lastif - iftot > 0) printf("%10.10s %8.8s %10.10s %8.8s %8.8s ", "packets", "errs", "packets", "errs", "colls"); putchar('\n'); fflush(stdout); line = 0; loop: sum->ift_ip = 0; sum->ift_ie = 0; sum->ift_op = 0; sum->ift_oe = 0; sum->ift_co = 0; memmove(varname, oid_ifinucastpkts, sizeof(oid_ifinucastpkts)); varname_len = sizeof(oid_ifinucastpkts) / sizeof(oid); ifentry = varname + 9; instance = varname + 10; for (ifnum = 1, ip = iftot; ifnum <= cfg_nnets && ip < lastif; ip++, ifnum++) { memset(now, 0, sizeof(*now)); *instance = ifnum; *ifentry = INUCASTPKTS; var = getvarbyname(Session, varname, varname_len); if (var) { now->ift_ip = *var->val.integer; snmp_free_var(var); } *ifentry = INNUCASTPKTS; var = getvarbyname(Session, varname, varname_len); if (var) { now->ift_ip += *var->val.integer; snmp_free_var(var); } *ifentry = INERRORS; var = getvarbyname(Session, varname, varname_len); if (var) { now->ift_ie = *var->val.integer; snmp_free_var(var); } *ifentry = OUTUCASTPKTS; var = getvarbyname(Session, varname, varname_len); if (var) { now->ift_op = *var->val.integer; snmp_free_var(var); } *ifentry = OUTNUCASTPKTS; var = getvarbyname(Session, varname, varname_len); if (var) { now->ift_op += *var->val.integer; snmp_free_var(var); } *ifentry = OUTERRORS; var = getvarbyname(Session, varname, varname_len); if (var) { now->ift_oe = *var->val.integer; snmp_free_var(var); } if (ip == interesting) printf("%10d %8d %10d %8d %8d ", now->ift_ip - ip->ift_ip, now->ift_ie - ip->ift_ie, now->ift_op - ip->ift_op, now->ift_oe - ip->ift_oe, now->ift_co - ip->ift_co); ip->ift_ip = now->ift_ip; ip->ift_ie = now->ift_ie; ip->ift_op = now->ift_op; ip->ift_oe = now->ift_oe; ip->ift_co = now->ift_co; sum->ift_ip += ip->ift_ip; sum->ift_ie += ip->ift_ie; sum->ift_op += ip->ift_op; sum->ift_oe += ip->ift_oe; sum->ift_co += ip->ift_co; } if (lastif - iftot > 0) printf("%10d %8d %10d %8d %8d ", sum->ift_ip - total->ift_ip, sum->ift_ie - total->ift_ie, sum->ift_op - total->ift_op, sum->ift_oe - total->ift_oe, sum->ift_co - total->ift_co); *total = *sum; putchar('\n'); fflush(stdout); line++; timerPause(); timerSet(interval); if (line == 21) goto banner; goto loop; /*NOTREACHED*/ }
/* * Print a description of the network interfaces. */ void intpro(int interval) { oid varname[MAX_OID_LEN], *instance, *ifentry; size_t varname_len; int ifnum, cfg_nnets; oid curifip [4]; struct variable_list *var; struct snmp_pdu *request, *response; int status; int ifindex, oldindex = 0; struct _if_info { int ifindex; char name[128]; char ip[128], route[128]; char ioctets[20], ierrs[20], ooctets[20], oerrs[20], outqueue[20]; int operstatus; u_long netmask; struct in_addr ifip, ifroute; } *if_table, *cur_if; int max_name = 4, max_route = 7, max_ip = 7, max_ioctets = 7, max_ooctets = 7; int i; if (interval) { sidewaysintpr((unsigned)interval); return; } var = getvarbyname(Session, oid_cfg_nnets, sizeof(oid_cfg_nnets) / sizeof(oid)); if (var && var->val.integer) { cfg_nnets = *var->val.integer; snmp_free_var(var); } else { fprintf (stderr, "No response when requesting number of interfaces.\n"); return; } DEBUGMSGTL (("netstat:if", "cfg_nnets = %d\n", cfg_nnets)); memset (curifip, 0, sizeof (curifip)); if_table = (struct _if_info *) calloc (cfg_nnets, sizeof (*if_table)); cur_if = if_table; for (ifnum = 1; ifnum <= cfg_nnets; ifnum++) { register char *cp; request = snmp_pdu_create (SNMP_MSG_GETNEXT); memmove (varname, oid_ipadentaddr, sizeof (oid_ipadentaddr)); varname_len = sizeof (oid_ipadentaddr) / sizeof (oid); instance = varname + 9; memmove (varname + 10, curifip, sizeof (curifip)); *instance = IPIFINDEX; snmp_add_null_var (request, varname, varname_len); *instance = IPADDR; snmp_add_null_var (request, varname, varname_len); *instance = IPNETMASK; snmp_add_null_var (request, varname, varname_len); status = snmp_synch_response (Session, request, &response); if (status != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR) { fprintf (stderr, "SNMP request failed for interface %d, variable %ld out of %d interfaces (IP)\n", ifnum, response->errindex, cfg_nnets); cfg_nnets = ifnum; break; } for (var = response->variables; var; var = var->next_variable) { if (snmp_get_do_debugging()) { print_variable (var->name, var->name_length, var); } switch (var->name [9]) { case IPIFINDEX: ifindex = *var->val.integer; for (cur_if = if_table; cur_if->ifindex != ifindex && cur_if->ifindex != 0; cur_if++); cur_if->ifindex = ifindex; break; case IPADDR: memmove (curifip, var->name+10, sizeof (curifip)); memmove (&cur_if->ifip, var->val.string, sizeof (u_long)); break; case IPNETMASK: memmove (&cur_if->netmask, var->val.string, sizeof (u_long)); } } cur_if->ifroute.s_addr = cur_if->ifip.s_addr & cur_if->netmask; if (cur_if->ifroute.s_addr) strcpy(cur_if->route, netname (cur_if->ifroute, cur_if->netmask)); else strcpy(cur_if->route, "none"); if ((i = strlen(cur_if->route)) > max_route) max_route = i; if (cur_if->ifip.s_addr) strcpy(cur_if->ip, routename (cur_if->ifip)); else strcpy(cur_if->ip, "none"); if ((i = strlen(cur_if->ip)) > max_ip) max_ip = i; snmp_free_pdu (response); memmove (varname, oid_ifname, sizeof(oid_ifname)); varname_len = sizeof(oid_ifname) / sizeof(oid); ifentry = varname + 9; instance = varname + 10; request = snmp_pdu_create (SNMP_MSG_GETNEXT); *instance = oldindex; *ifentry = IFINDEX; snmp_add_null_var (request, varname, varname_len); *ifentry = IFNAME; snmp_add_null_var (request, varname, varname_len); *ifentry = IFOPERSTATUS; snmp_add_null_var (request, varname, varname_len); *ifentry = INOCTETS; snmp_add_null_var (request, varname, varname_len); *ifentry = OUTOCTETS; snmp_add_null_var (request, varname, varname_len); while ((status = snmp_synch_response (Session, request, &response)) == STAT_SUCCESS) { if (response->errstat != SNMP_ERR_NOSUCHNAME) break; if ((request = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) == NULL) break; snmp_free_pdu(response); } if (status != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR) { fprintf (stderr, "SNMP request failed for interface %d, variable %ld out of %d interfaces (IF)\n", ifnum, response->errindex, cfg_nnets); cfg_nnets = ifnum; break; } for (var = response->variables; var; var = var->next_variable) { if (snmp_get_do_debugging()) { print_variable (var->name, var->name_length, var); } if (!var->val.integer) continue; switch (var->name [9]) { case IFINDEX: ifindex = *var->val.integer; for (cur_if = if_table; cur_if->ifindex != ifindex && cur_if->ifindex != 0; cur_if++); cur_if->ifindex = ifindex; break; case INOCTETS: sprintf(cur_if->ioctets, "%lu", *var->val.integer); i = strlen(cur_if->ioctets); if (i > max_ioctets) max_ioctets = i; break; case OUTOCTETS: sprintf(cur_if->ooctets, "%lu", *var->val.integer); i = strlen(cur_if->ooctets); if (i > max_ooctets) max_ooctets = i; break; case IFNAME: oldindex = var->name[10]; if (var->val_len >= sizeof(cur_if->name)) var->val_len = sizeof(cur_if->name) - 1; memmove (cur_if->name, var->val.string, var->val_len); cur_if->name [var->val_len] = 0; if ((i = strlen(cur_if->name)+1) > max_name) max_name = i; break; case IFOPERSTATUS: cur_if->operstatus = *var->val.integer; break; } } snmp_free_pdu (response); if (intrface != NULL && strcmp(cur_if->name, intrface) != 0) { cur_if->name [0] = 0; continue; } if (cur_if->operstatus != MIB_IFSTATUS_UP) { cp = strchr(cur_if->name, '\0'); *cp++ = '*'; *cp = '\0'; } } printf("%*.*s %*.*s %*.*s %*.*s %*.*s ", -max_name, max_name, "Name", -max_route, max_route, "Network", -max_ip, max_ip, "Address", max_ioctets, max_ioctets, "Ioctets", max_ooctets, max_ooctets, "Ooctets"); putchar('\n'); for (ifnum = 0, cur_if = if_table; ifnum < cfg_nnets; ifnum++, cur_if++) { if (cur_if->name [0] == 0) continue; printf("%*.*s ", -max_name, max_name, cur_if->name); printf("%*.*s ", -max_route, max_route, cur_if->route); printf("%*.*s ", -max_ip, max_ip, cur_if->ip); printf("%*s %*s", max_ioctets, cur_if->ioctets, max_ioctets, cur_if->ooctets); putchar('\n'); } free(if_table); }
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; }
/* only accepts read-only data */ int sipOtherStatsTable_replaceRow( struct sip_snmp_obj *idx, struct sip_snmp_obj *data) { netsnmp_table_row *row; netsnmp_variable_list *idxs=NULL; struct sip_snmp_obj *o; int col; static int applIndex = -1; const char *func = "snmp_mod"; if(applIndex == -1) { applIndex = ser_getApplIndex(); if(applIndex == -1 ) { LOG(L_ERR, "%s: Error while looking for previous row\n", func); return -1; } } /* create index list */ if(snmp_varlist_add_variable(&idxs, NULL, 0, ASN_INTEGER, (u_char*)&applIndex, sizeof(applIndex)) == NULL) { LOG(L_ERR, "%s: Error while looking for previous row\n", func); return -1; } o = idx; while(o) { if(snmp_varlist_add_variable(&idxs, NULL, 0, ser_types[o->type], o->value.voidp, o->val_len) == NULL) { LOG(L_ERR, "%s: Error while looking for row to replace\n", func); snmp_free_var(idxs); return -1; } o = o->next; } /* find row */ row = netsnmp_table_data_get(sipOtherStatsTable->table, idxs); if(!row) { LOG(L_ERR, "%s: Couldn't find row to replace\n", func); snmp_free_var(idxs); return -1; } snmp_free_var(idxs); /* add the data */ o = data; col = 2; while(o) { if(col > SIPOTHERSTATSTABLE_COLUMNS) { LOG(L_ERR, "%s: Too many columns to add\n", func); return -1; } if(!o->value.voidp) { LOG(L_ERR, "%s: Invalid object to add\n", func); return -1; } o->col = col; /* all previous objects are left in the row */ if(netsnmp_set_row_column(row, col, ser_types[o->type], o->value.voidp, o->val_len) != SNMPERR_SUCCESS) { LOG(L_ERR, "%s: Error adding object to row\n", func); return -1; } o=o->next; col++; } return 0; }
int write_snmpNotifyFilterProfileRowStatus(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, u_char * statP, oid * name, size_t name_len) { struct snmpNotifyFilterProfileTable_data *StorageTmp = NULL; static struct snmpNotifyFilterProfileTable_data *StorageDel; size_t newlen = name_len - (sizeof(snmpNotifyFilterProfileTable_variables_oid) / sizeof(oid) + 3 - 1); static int old_value; int set_value = *((long *) var_val); netsnmp_variable_list *vars; struct header_complex_index *hciptr; DEBUGMSGTL(("snmpNotifyFilterProfileTable", "write_snmpNotifyFilterProfileRowStatus entering action=%d... \n", action)); StorageTmp = (struct snmpNotifyFilterProfileTable_data *) header_complex((struct header_complex_index *) snmpNotifyFilterProfileTableStorage, NULL, &name[sizeof (snmpNotifyFilterProfileTable_variables_oid) / sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL); switch (action) { case RESERVE1: if (var_val_type != ASN_INTEGER || var_val == NULL) { return SNMP_ERR_WRONGTYPE; } if (var_val_len != sizeof(long)) { return SNMP_ERR_WRONGLENGTH; } if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY) { return SNMP_ERR_WRONGVALUE; } /* * stage one: test validity */ if (StorageTmp == NULL) { /* * create the row now? */ /* * ditch illegal values now */ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) { return SNMP_ERR_INCONSISTENTVALUE; } } else { /* * row exists. Check for a valid state change */ if (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT) { /* * can't create a row that exists */ return SNMP_ERR_INCONSISTENTVALUE; } if ((set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) && StorageTmp->snmpNotifyFilterProfileNameLen == 0) { /* * can't activate row without a profile name */ return SNMP_ERR_INCONSISTENTVALUE; } /* * XXX: interaction with row storage type needed */ } /* * memory reseveration, final preparation... */ if (StorageTmp == NULL && (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT)) { /* * creation */ vars = NULL; snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OCTET_STR, NULL, 0); if (header_complex_parse_oid (& (name [sizeof(snmpNotifyFilterProfileTable_variables_oid) / sizeof(oid) + 2]), newlen, vars) != SNMPERR_SUCCESS) { snmp_free_var(vars); return SNMP_ERR_INCONSISTENTNAME; } StorageNew = SNMP_MALLOC_STRUCT(snmpNotifyFilterProfileTable_data); if (StorageNew == NULL) return SNMP_ERR_GENERR; memdup((u_char **) & (StorageNew->snmpTargetParamsName), vars->val.string, vars->val_len); StorageNew->snmpTargetParamsNameLen = vars->val_len; StorageNew->snmpNotifyFilterProfileStorType = ST_NONVOLATILE; StorageNew->snmpNotifyFilterProfileRowStatus = RS_NOTREADY; snmp_free_var(vars); } break; case RESERVE2: break; case FREE: /* * XXX: free, zero vars */ /* * Release any resources that have been allocated */ if (StorageNew != NULL) { SNMP_FREE(StorageNew->snmpTargetParamsName); SNMP_FREE(StorageNew->snmpNotifyFilterProfileName); free(StorageNew); StorageNew = NULL; } break; case ACTION: /* * The variable has been stored in set_value for you to * use, and you have just been asked to do something with * it. Note that anything done here must be reversable in * the UNDO case */ if (StorageTmp == NULL && (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT)) { /* * row creation, so add it */ if (StorageNew != NULL) snmpNotifyFilterProfileTable_add(StorageNew); /* * XXX: ack, and if it is NULL? */ } else if (set_value != RS_DESTROY) { /* * set the flag? */ if (StorageTmp == NULL) return SNMP_ERR_GENERR; /* should never ever get here */ old_value = StorageTmp->snmpNotifyFilterProfileRowStatus; StorageTmp->snmpNotifyFilterProfileRowStatus = *((long *) var_val); } else { /* * destroy... extract it for now */ if (StorageTmp) { hciptr = header_complex_find_entry (snmpNotifyFilterProfileTableStorage, StorageTmp); StorageDel = (struct snmpNotifyFilterProfileTable_data *) header_complex_extract_entry((struct header_complex_index **) &snmpNotifyFilterProfileTableStorage, hciptr); } } break; case UNDO: /* * Back out any changes made in the ACTION case */ if (StorageTmp == NULL && (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT)) { /* * row creation, so remove it again */ hciptr = header_complex_find_entry (snmpNotifyFilterProfileTableStorage, StorageNew); StorageDel = (struct snmpNotifyFilterProfileTable_data *) header_complex_extract_entry((struct header_complex_index **) &snmpNotifyFilterProfileTableStorage, hciptr); /* * XXX: free it */ } else if (StorageDel != NULL) { /* * row deletion, so add it again */ snmpNotifyFilterProfileTable_add(StorageDel); StorageDel = NULL; } else if (set_value != RS_DESTROY) { if (StorageTmp) StorageTmp->snmpNotifyFilterProfileRowStatus = old_value; } break; case COMMIT: /* * Things are working well, so it's now safe to make the change * permanently. Make sure that anything done here can't fail! */ if (StorageDel != NULL) { SNMP_FREE(StorageDel->snmpTargetParamsName); SNMP_FREE(StorageDel->snmpNotifyFilterProfileName); free(StorageDel); StorageDel = NULL; } if (StorageTmp && set_value == RS_CREATEANDGO) { if (StorageTmp->snmpNotifyFilterProfileNameLen) StorageTmp->snmpNotifyFilterProfileRowStatus = RS_ACTIVE; StorageNew = NULL; } else if (StorageTmp && set_value == RS_CREATEANDWAIT) { if (StorageTmp->snmpNotifyFilterProfileNameLen) StorageTmp->snmpNotifyFilterProfileRowStatus = RS_NOTINSERVICE; StorageNew = NULL; } snmp_store_needed(NULL); break; } return SNMP_ERR_NOERROR; }
int unregister_index(struct variable_list *varbind, int remember, struct snmp_session *ss) { struct snmp_index *idxptr, *idxptr2; struct snmp_index *prev_oid_ptr, *prev_idx_ptr; int res, res2, i; #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING) if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT ) return( agentx_unregister_index( ss, varbind )); #endif /* Look for the requested OID entry */ prev_oid_ptr = NULL; prev_idx_ptr = NULL; res = 1; res2 = 1; for( idxptr = snmp_index_head ; idxptr != NULL; prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) { if ((res = snmp_oid_compare(varbind->name, varbind->name_length, idxptr->varbind.name, idxptr->varbind.name_length)) <= 0 ) break; } if ( res != 0 ) return INDEX_ERR_NOT_ALLOCATED; if ( varbind->type != idxptr->varbind.type ) return INDEX_ERR_WRONG_TYPE; for(idxptr2 = idxptr ; idxptr2 != NULL; prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { i = SNMP_MIN(varbind->val_len, idxptr2->varbind.val_len); res2 = memcmp(varbind->val.string, idxptr2->varbind.val.string, i); if ( res2 <= 0 ) break; } if ( res2 != 0 ) return INDEX_ERR_NOT_ALLOCATED; if ( ss != idxptr2->session ) return INDEX_ERR_WRONG_SESSION; /* * If this is a "normal" index unregistration, * mark the index entry as unused, but leave * it in situ. This allows differentiation * between ANY_INDEX and NEW_INDEX */ if ( remember ) { idxptr2->session = NULL; /* Unused index */ return SNMP_ERR_NOERROR; } /* * If this is a failed attempt to register a * number of indexes, the successful ones * must be removed completely. */ if ( prev_idx_ptr ) { prev_idx_ptr->next_idx = idxptr2->next_idx; } else if ( prev_oid_ptr ) { if ( idxptr2->next_idx ) /* Use p_idx_ptr as a temp variable */ prev_idx_ptr = idxptr2->next_idx; else prev_idx_ptr = idxptr2->next_oid; while ( prev_oid_ptr ) { prev_oid_ptr->next_oid = prev_idx_ptr; prev_oid_ptr = prev_oid_ptr->next_idx; } } else { if ( idxptr2->next_idx ) snmp_index_head = idxptr2->next_idx; else snmp_index_head = idxptr2->next_oid; } snmp_free_var( (struct variable_list *)idxptr2 ); return SNMP_ERR_NOERROR; }
/* * Dump ICMP statistics. */ void icmp_stats(void) { oid varname[MAX_OID_LEN], *icmpentry; int varname_len; netsnmp_variable_list *var; int count, first; struct stat_table *sp; memmove(varname, oid_icmpstats, sizeof(oid_icmpstats)); varname_len = sizeof(oid_icmpstats) / sizeof(oid); icmpentry = varname + 7; printf("icmp:\n"); sp = icmp_stattab; count = sizeof(icmp_stattab) / sizeof(struct stat_table); while (count--) { *icmpentry = sp->entry; var = getvarbyname(Session, varname, varname_len); if (var && var->val.integer) { putchar('\t'); printf(sp->description, *var->val.integer, plural((int) *var->val.integer)); putchar('\n'); } if (var) snmp_free_var(var); sp++; } sp = icmp_outhistogram; first = 1; count = sizeof(icmp_outhistogram) / sizeof(struct stat_table); while (count--) { *icmpentry = sp->entry; var = getvarbyname(Session, varname, varname_len); if (var && var->val.integer && *var->val.integer != 0) { if (first) { printf("\tOutput Histogram:\n"); first = 0; } printf("\t\t"); printf(sp->description, *var->val.integer, plural((int) *var->val.integer)); putchar('\n'); } if (var) snmp_free_var(var); sp++; } sp = icmp_inhistogram; first = 1; count = sizeof(icmp_inhistogram) / sizeof(struct stat_table); while (count--) { *icmpentry = sp->entry; var = getvarbyname(Session, varname, varname_len); if (var && var->val.integer && *var->val.integer != 0) { if (first) { printf("\tInput Histogram:\n"); first = 0; } printf("\t\t"); printf(sp->description, *var->val.integer, plural((int) *var->val.integer)); putchar('\n'); } if (var) snmp_free_var(var); sp++; } }