int add_agent_caps_list(netsnmp_session * session, netsnmp_pdu *pdu) { netsnmp_session *sp; char* description; sp = find_agentx_session(session, pdu->sessid); if (sp == NULL) return AGENTX_ERR_NOT_OPEN; description = netsnmp_strdup_and_null(pdu->variables->val.string, pdu->variables->val_len); register_sysORTable_sess(pdu->variables->name, pdu->variables->name_length, description, sp); free(description); return AGENTX_ERR_NOERROR; }
/* * send trap */ void run_mte_events(struct mteTriggerTable_data *item, oid * name_oid, size_t name_oid_len, const char *eventobjowner, const char *eventobjname) { static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapIOD.0 */ netsnmp_variable_list *var_list = NULL; netsnmp_table_row *row, *notif_row; netsnmp_table_data_set_storage *col1, *tc, *no, *noo; for(row = table_set->table->first_row; row; row = row->next) { if (strcmp(row->indexes->val.string, eventobjowner) == 0 && strcmp(row->indexes->next_variable->val.string, eventobjname) == 0) { /* run this event */ col1 = (netsnmp_table_data_set_storage *) row->data; tc = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTACTIONS); if (!tc->data.bitstring[0] & 0x80) { /* not a notification. next! (XXX: do sets) */ continue; } tc = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTENABLED); if (*(tc->data.integer) != 1) { /* not enabled. next! */ continue; } if (!mteEventNotif_table_set) { /* no notification info */ continue; } /* send the notification */ var_list = NULL; /* XXX: get notif information */ for(notif_row = mteEventNotif_table_set->table->first_row; notif_row; notif_row = notif_row->next) { if (strcmp(notif_row->indexes->val.string, eventobjowner) == 0 && strcmp(notif_row->indexes->next_variable->val.string, eventobjname) == 0) { /* run this event */ col1 = (netsnmp_table_data_set_storage *) notif_row->data; tc = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATION); no = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATIONOBJECTS); noo = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER); if (!tc) continue; /* no notification to be had. XXX: return? */ /* * snmpTrap oid */ snmp_varlist_add_variable(&var_list, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid), ASN_OBJECT_ID, (u_char *) tc->data.objid, tc->data_len); /* XXX: add objects from the mteObjectsTable */ DEBUGMSGTL(("mteEventTable:send_events", "no: %x, no->data: %s", no, no->data.string)); DEBUGMSGTL(("mteEventTable:send_events", "noo: %x, noo->data: %s", noo, noo->data.string)); DEBUGMSGTL(("mteEventTable:send_events", "name_oid: %x",name_oid)); if (no && no->data.string && noo && noo->data.string && name_oid) { char *tmpowner = netsnmp_strdup_and_null(noo->data.string, noo->data_len); char *tmpname = netsnmp_strdup_and_null(no->data.string, no->data_len); DEBUGMSGTL(("mteEventTable:send_events", "Adding objects for owner=%s name=%s", tmpowner, tmpname)); mte_add_objects(var_list, item, tmpowner, tmpname, name_oid + item->mteTriggerValueIDLen, name_oid_len - item->mteTriggerValueIDLen); free(tmpowner); free(tmpname); } DEBUGMSGTL(("mteEventTable:send_events", "sending an event ")); DEBUGMSGOID(("mteEventTable:send_events", tc->data.objid, tc->data_len / sizeof(oid))); DEBUGMSG(("mteEventTable:send_events", "\n")); send_v2trap(var_list); snmp_free_varbind(var_list); } } } } }
/** implements the table data helper. This is the routine that takes * care of all SNMP requests coming into the table. */ int netsnmp_table_data_set_helper_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_table_data_set_storage *data = NULL; newrow_stash *newrowstash = NULL; netsnmp_table_row *row, *newrow = NULL; netsnmp_table_request_info *table_info; netsnmp_request_info *request; oid *suffix; size_t suffix_len; netsnmp_oid_stash_node **stashp = NULL; if (!handler) return SNMPERR_GENERR; DEBUGMSGTL(("netsnmp_table_data_set", "handler starting\n")); for (request = requests; request; request = request->next) { netsnmp_table_data_set *datatable = (netsnmp_table_data_set *) handler->myvoid; if (request->processed) continue; /* * extract our stored data and table info */ row = netsnmp_extract_table_row(request); table_info = netsnmp_extract_table_info(request); suffix = requests->requestvb->name + reginfo->rootoid_len + 2; suffix_len = requests->requestvb->name_length - (reginfo->rootoid_len + 2); if (MODE_IS_SET(reqinfo->mode)) { char buf[256]; /* is this reasonable size?? */ int rc; size_t len; /* * use a cached copy of the row for modification */ /* * cache location: may have been created already by other * SET requests in the same master request. */ rc = snprintf(buf, sizeof(buf), "dataset_row_stash:%s:", datatable->table->name); if ((-1 == rc) || (rc >= sizeof(buf))) { snmp_log(LOG_ERR,"%s handler name too long\n", datatable->table->name); netsnmp_set_request_error(reqinfo, request, SNMP_ERR_GENERR); continue; } len = sizeof(buf) - rc; rc = snprint_objid(&buf[rc], len, table_info->index_oid, table_info->index_oid_len); if (-1 == rc) { snmp_log(LOG_ERR,"%s oid or name too long\n", datatable->table->name); netsnmp_set_request_error(reqinfo, request, SNMP_ERR_GENERR); continue; } stashp = (netsnmp_oid_stash_node **) netsnmp_table_get_or_create_row_stash(reqinfo, buf); newrowstash = netsnmp_oid_stash_get_data(*stashp, suffix, suffix_len); if (!newrowstash) { if (!row) { if (datatable->allow_creation) { /* * entirely new row. Create the row from the template */ newrowstash = netsnmp_table_data_set_create_newrowstash( datatable, table_info); newrow = newrowstash->newrow; } else if (datatable->rowstatus_column == 0) { /* * A RowStatus object may be used to control the * creation of a new row. But if this object * isn't declared (and the table isn't marked as * 'auto-create'), then we can't create a new row. */ netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOCREATION); continue; } } else { /* * existing row that needs to be modified */ newrowstash = SNMP_MALLOC_TYPEDEF(newrow_stash); newrow = netsnmp_table_data_set_clone_row(row); newrowstash->newrow = newrow; } netsnmp_oid_stash_add_data(stashp, suffix, suffix_len, newrowstash); } else { newrow = newrowstash->newrow; } /* * all future SET data modification operations use this * temp pointer */ if (reqinfo->mode == MODE_SET_RESERVE1 || reqinfo->mode == MODE_SET_RESERVE2) row = newrow; } if (row) data = (netsnmp_table_data_set_storage *) row->data; if (!row || !table_info || !data) { if (!MODE_IS_SET(reqinfo->mode)) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } } data = netsnmp_table_data_set_find_column(data, table_info->colnum); switch (reqinfo->mode) { case MODE_GET: case MODE_GETNEXT: case MODE_GETBULK: /* XXXWWW */ if (data && data->data.voidp) netsnmp_table_data_build_result(reginfo, reqinfo, request, row, table_info->colnum, data->type, data->data.voidp, data->data_len); break; case MODE_SET_RESERVE1: if (data) { /* * Can we modify the existing row? */ if (!data->writable) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOTWRITABLE); } else if (request->requestvb->type != data->type) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); } } else if (datatable->rowstatus_column == table_info->colnum) { /* * Otherwise, this is where we create a new row using * the RowStatus object (essentially duplicating the * steps followed earlier in the 'allow_creation' case) */ switch (*(request->requestvb->val.integer)) { case RS_CREATEANDGO: case RS_CREATEANDWAIT: newrowstash = netsnmp_table_data_set_create_newrowstash( datatable, table_info); newrow = newrowstash->newrow; row = newrow; netsnmp_oid_stash_add_data(stashp, suffix, suffix_len, newrowstash); } } break; case MODE_SET_RESERVE2: /* * If the agent receives a SET request for an object in a non-existant * row, then the RESERVE1 pass will create the row automatically. * * But since the row doesn't exist at that point, the test for whether * the object is writable or not will be skipped. So we need to check * for this possibility again here. * * Similarly, if row creation is under the control of the RowStatus * object (i.e. allow_creation == 0), but this particular request * doesn't include such an object, then the row won't have been created, * and the writable check will also have been skipped. Again - check here. */ if (data && data->writable == 0) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOTWRITABLE); continue; } if (datatable->rowstatus_column == table_info->colnum) { switch (*(request->requestvb->val.integer)) { case RS_ACTIVE: case RS_NOTINSERVICE: /* * Can only operate on pre-existing rows. */ if (!newrowstash || newrowstash->created) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_INCONSISTENTVALUE); continue; } break; case RS_CREATEANDGO: case RS_CREATEANDWAIT: /* * Can only operate on newly created rows. */ if (!(newrowstash && newrowstash->created)) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_INCONSISTENTVALUE); continue; } break; case RS_DESTROY: /* * Can operate on new or pre-existing rows. */ break; case RS_NOTREADY: default: /* * Not a valid value to Set */ netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); continue; } } if (!data ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOCREATION); continue; } /* * modify row and set new value */ SNMP_FREE(data->data.string); data->data.string = netsnmp_strdup_and_null(request->requestvb->val.string, request->requestvb->val_len); if (!data->data.string) { netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE); } data->data_len = request->requestvb->val_len; if (datatable->rowstatus_column == table_info->colnum) { switch (*(request->requestvb->val.integer)) { case RS_CREATEANDGO: /* * XXX: check legality */ *(data->data.integer) = RS_ACTIVE; break; case RS_CREATEANDWAIT: /* * XXX: check legality */ *(data->data.integer) = RS_NOTINSERVICE; break; case RS_DESTROY: newrowstash->deleted = 1; break; } } break; case MODE_SET_ACTION: /* * Install the new row into the stored table. * Do this only *once* per row .... */ if (newrowstash->state != STATE_ACTION) { newrowstash->state = STATE_ACTION; if (newrowstash->created) { netsnmp_table_dataset_add_row(datatable, newrow); } else { netsnmp_table_dataset_replace_row(datatable, row, newrow); } } /* * ... but every (relevant) varbind in the request will * need to know about this new row, so update the * per-request row information regardless */ if (newrowstash->created) { netsnmp_request_add_list_data(request, netsnmp_create_data_list(TABLE_DATA_NAME, newrow, NULL)); } break; case MODE_SET_UNDO: /* * extract the new row, replace with the old or delete */ if (newrowstash->state != STATE_UNDO) { newrowstash->state = STATE_UNDO; if (newrowstash->created) { netsnmp_table_dataset_remove_and_delete_row(datatable, newrow); } else { netsnmp_table_dataset_replace_row(datatable, newrow, row); netsnmp_table_dataset_delete_row(newrow); } } break; case MODE_SET_COMMIT: if (newrowstash->state != STATE_COMMIT) { newrowstash->state = STATE_COMMIT; if (!newrowstash->created) { netsnmp_table_dataset_delete_row(row); } if (newrowstash->deleted) { netsnmp_table_dataset_remove_and_delete_row(datatable, newrow); } } break; case MODE_SET_FREE: if (newrowstash && newrowstash->state != STATE_FREE) { newrowstash->state = STATE_FREE; netsnmp_table_dataset_delete_row(newrow); } break; } } /* next handler called automatically - 'AUTO_NEXT' */ return SNMP_ERR_NOERROR; }
/* * save info from incoming trap * * return 0 on success, anything else is an error */ static int _sql_save_trap_info(sql_buf *sqlb, netsnmp_pdu *pdu, netsnmp_transport *transport) { static oid trapoids[] = { 1, 3, 6, 1, 6, 3, 1, 1, 5, 0 }; oid *trap_oid, tmp_oid[MAX_OID_LEN]; time_t now; struct tm *cur_time; size_t tmp_size; size_t buf_host_len_t, buf_oid_len_t, buf_user_len_t; int oid_overflow, trap_oid_len; netsnmp_variable_list *vars; if ((NULL == sqlb) || (NULL == pdu) || (NULL == transport)) return -1; DEBUGMSGTL(("sql:queue", "queueing incoming trap\n")); /** time */ (void) time(&now); cur_time = localtime(&now); sqlb->time.year = cur_time->tm_year + 1900; sqlb->time.month = cur_time->tm_mon + 1; sqlb->time.day = cur_time->tm_mday; sqlb->time.hour = cur_time->tm_hour; sqlb->time.minute = cur_time->tm_min; sqlb->time.second = cur_time->tm_sec; sqlb->time.second_part = 0; sqlb->time.neg = 0; /** host name */ buf_host_len_t = 0; tmp_size = sizeof(sqlb->host); realloc_format_trap((u_char**)&sqlb->host, &tmp_size, &buf_host_len_t, 1, "%B", pdu, transport); sqlb->host_len = buf_host_len_t; /* snmpTrapOID */ if (pdu->command == SNMP_MSG_TRAP) { /* * convert a v1 trap to a v2 varbind */ if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) { trap_oid_len = pdu->enterprise_length; memcpy(tmp_oid, pdu->enterprise, sizeof(oid) * trap_oid_len); if (tmp_oid[trap_oid_len - 1] != 0) tmp_oid[trap_oid_len++] = 0; tmp_oid[trap_oid_len++] = pdu->specific_type; trap_oid = tmp_oid; } else { trapoids[9] = pdu->trap_type + 1; trap_oid = trapoids; trap_oid_len = OID_LENGTH(trapoids); } } else { vars = pdu->variables; if (vars && vars->next_variable) { trap_oid_len = vars->next_variable->val_len / sizeof(oid); trap_oid = vars->next_variable->val.objid; } else { static oid null_oid[] = { 0, 0 }; trap_oid_len = OID_LENGTH(null_oid); trap_oid = null_oid; } } tmp_size = 0; buf_oid_len_t = oid_overflow = 0; netsnmp_sprint_realloc_objid_tree((u_char**)&sqlb->oid,&tmp_size, &buf_oid_len_t, 1, &oid_overflow, trap_oid, trap_oid_len); sqlb->oid_len = buf_oid_len_t; if (oid_overflow) snmp_log(LOG_WARNING,"OID truncated in sql buffer\n"); /** request id */ sqlb->reqid = pdu->reqid; /** version (convert to 1 based, for sql enum) */ sqlb->version = pdu->version + 1; /** command type (convert to 1 based, for sql enum) */ sqlb->type = pdu->command - 159; /** community string/user name */ tmp_size = 0; buf_user_len_t = 0; realloc_format_trap((u_char**)&sqlb->user, &tmp_size, &buf_user_len_t, 1, "%u", pdu, transport); sqlb->user_len = buf_user_len_t; /** transport */ sqlb->transport = transport->f_fmtaddr(transport, pdu->transport_data, pdu->transport_data_length); /** security model */ sqlb->security_model = pdu->securityModel; if ((SNMP_MP_MODEL_SNMPv3+1) == sqlb->version) { sqlb->msgid = pdu->msgid; sqlb->security_level = pdu->securityLevel; if (pdu->contextName) { sqlb->context = netsnmp_strdup_and_null((u_char*)pdu->contextName, pdu->contextNameLen); sqlb->context_len = pdu->contextNameLen; } if (pdu->contextEngineID) { sqlb->context_engine_len = binary_to_hex(pdu->contextEngineID, pdu->contextEngineIDLen, &sqlb->context_engine); } if (pdu->securityName) { sqlb->security_name = netsnmp_strdup_and_null((u_char*)pdu->securityName, pdu->securityNameLen); sqlb->security_name_len = pdu->securityNameLen; } if (pdu->securityEngineID) { sqlb->security_engine_len = binary_to_hex(pdu->securityEngineID, pdu->securityEngineIDLen, &sqlb->security_engine); } } return 0; }
int write_mteTriggerBooleanEvent (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) { static char *tmpvar; struct mteTriggerTable_data *StorageTmp = NULL; static size_t tmplen; size_t newlen = name_len - (sizeof (mteTriggerBooleanTable_variables_oid) / sizeof (oid) + 3 - 1); DEBUGMSGTL (("mteTriggerBooleanTable", "write_mteTriggerBooleanEvent entering action=%d... \n", action)); if ((StorageTmp = header_complex (mteTriggerTableStorage, NULL, &name[sizeof (mteTriggerBooleanTable_variables_oid) / sizeof (oid) + 3 - 1], &newlen, 1, NULL, NULL)) == NULL) return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */ switch (action) { case RESERVE1: if (var_val_type != ASN_OCTET_STR) { fprintf (stderr, "write to mteTriggerBooleanEvent not ASN_OCTET_STR\n"); return SNMP_ERR_WRONGTYPE; } if (StorageTmp->storageType != ST_NONVOLATILE) return SNMP_ERR_NOTWRITABLE; break; case RESERVE2: /* * memory reseveration, final preparation... */ break; case FREE: /* * Release any resources that have been allocated */ break; case ACTION: /* * The variable has been stored in string 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 */ tmpvar = StorageTmp->mteTriggerBooleanEvent; tmplen = StorageTmp->mteTriggerBooleanEventLen; StorageTmp->mteTriggerBooleanEvent = netsnmp_strdup_and_null (var_val, var_val_len); StorageTmp->mteTriggerBooleanEventLen = var_val_len; break; case UNDO: /* * Back out any changes made in the ACTION case */ SNMP_FREE (StorageTmp->mteTriggerBooleanEvent); StorageTmp->mteTriggerBooleanEvent = tmpvar; StorageTmp->mteTriggerBooleanEventLen = tmplen; 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! */ SNMP_FREE (tmpvar); break; } return SNMP_ERR_NOERROR; }
int mte_add_object_to_table(const char *owner, const char *objname, oid * oidname, size_t oidname_len, int iswild) { struct header_complex_index *hcptr = mteObjectsTableStorage, *lastnode; static struct mteObjectsTable_data *StorageNew; /* * malloc initial struct */ StorageNew = SNMP_MALLOC_STRUCT(mteObjectsTable_data); if (StorageNew == NULL) return SNMP_ERR_GENERR; StorageNew->mteOwner = netsnmp_strdup_and_null(owner, strlen(owner)); StorageNew->mteOwnerLen = strlen(owner); StorageNew->mteObjectsName = netsnmp_strdup_and_null(objname, strlen(objname)); StorageNew->mteObjectsNameLen = strlen(objname); /* * find the next number */ /* * get to start of objects list */ while (hcptr && (strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner, owner) != 0 || strcmp(((struct mteObjectsTable_data *) hcptr->data)-> mteObjectsName, objname) != 0)) hcptr = hcptr->next; if (hcptr) { /* * an object existed. Find the first one past and increment * the previous number */ lastnode = hcptr; while (hcptr && strcmp(((struct mteObjectsTable_data *) hcptr->data)-> mteOwner, owner) == 0 && strcmp(((struct mteObjectsTable_data *) hcptr->data)-> mteObjectsName, objname) == 0) { lastnode = hcptr; hcptr = hcptr->next; } StorageNew->mteObjectsIndex = ((struct mteObjectsTable_data *) lastnode->data)-> mteObjectsIndex + 1; } else { StorageNew->mteObjectsIndex = 1; } /* * XXX: fill in default row values here into StorageNew */ StorageNew->mteObjectsID = snmp_duplicate_objid(oidname, oidname_len); StorageNew->mteObjectsIDLen = oidname_len; if (iswild) StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_TRUE; else StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_FALSE; StorageNew->mteObjectsEntryStatus = RS_ACTIVE; StorageNew->storagetype = ST_READONLY; return mteObjectsTable_add(StorageNew); }
int write_mteObjectsEntryStatus(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 mteObjectsTable_data *StorageTmp = NULL; static struct mteObjectsTable_data *StorageNew, *StorageDel; size_t newlen = name_len - (sizeof(mteObjectsTable_variables_oid) / sizeof(oid) + 3 - 1); static int old_value; int set_value; static netsnmp_variable_list *vars, *vp; struct header_complex_index *hciptr; StorageTmp = header_complex(mteObjectsTableStorage, NULL, &name[sizeof(mteObjectsTable_variables_oid) / sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL); if (var_val_type != ASN_INTEGER || var_val == NULL) { snmp_log(LOG_ERR, "write to mteObjectsEntryStatus not ASN_INTEGER\n"); return SNMP_ERR_WRONGTYPE; } if (StorageTmp && StorageTmp->storagetype == ST_READONLY) { return SNMP_ERR_NOTWRITABLE; } set_value = *((long *) var_val); /* * check legal range, and notReady is reserved for us, not a user */ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY) return SNMP_ERR_INCONSISTENTVALUE; switch (action) { case RESERVE1: /* * 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; /* * destroying a non-existent row is actually legal */ if (set_value == RS_DESTROY) { return SNMP_ERR_NOERROR; } /* * illegal creation values */ 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 */ } break; case RESERVE2: /* * memory reseveration, final preparation... */ if (StorageTmp == NULL) { /* * creation */ vars = NULL; snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* mteOwner */ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* mteObjectsName */ snmp_varlist_add_variable(&vars, NULL, 0, ASN_UNSIGNED, NULL, 0); /* mteObjectsIndex */ if (header_complex_parse_oid (& (name [sizeof(mteObjectsTable_variables_oid) / sizeof(oid) + 2]), newlen, vars) != SNMPERR_SUCCESS) { /* * XXX: free, zero vars */ return SNMP_ERR_INCONSISTENTNAME; } vp = vars; StorageNew = SNMP_MALLOC_STRUCT(mteObjectsTable_data); if (StorageNew == NULL) return SNMP_ERR_GENERR; StorageNew->mteOwner = netsnmp_strdup_and_null(vp->val.string, vp->val_len); StorageNew->mteOwnerLen = vp->val_len; vp = vp->next_variable; StorageNew->mteObjectsName = netsnmp_strdup_and_null(vp->val.string, vp->val_len); StorageNew->mteObjectsNameLen = vp->val_len; vp = vp->next_variable; StorageNew->mteObjectsIndex = *(vp->val.integer); /* * XXX: fill in default row values here into StorageNew */ StorageNew->mteObjectsID = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0 */ StorageNew->mteObjectsIDLen = 2; StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_FALSE; StorageNew->mteObjectsEntryStatus = set_value; /* * XXX: free, zero vars, no longer needed? */ } break; case FREE: /* * XXX: free, zero vars */ /* * Release any resources that have been allocated */ 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) { /* * row creation, so add it */ if (StorageNew != NULL) mteObjectsTable_add(StorageNew); /* * XXX: ack, and if it is NULL? */ } else if (set_value != RS_DESTROY) { /* * set the flag? */ old_value = StorageTmp->mteObjectsEntryStatus; StorageTmp->mteObjectsEntryStatus = *((long *) var_val); } else { /* * destroy... extract it for now */ hciptr = header_complex_find_entry(mteObjectsTableStorage, StorageTmp); StorageDel = header_complex_extract_entry(&mteObjectsTableStorage, hciptr); } break; case UNDO: /* * Back out any changes made in the ACTION case */ if (StorageTmp == NULL) { /* * row creation, so remove it again */ hciptr = header_complex_find_entry(mteObjectsTableStorage, StorageTmp); StorageDel = header_complex_extract_entry(&mteObjectsTableStorage, hciptr); /* * XXX: free it */ } else if (StorageDel != NULL) { /* * row deletion, so add it again */ mteObjectsTable_add(StorageDel); } else { StorageTmp->mteObjectsEntryStatus = 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) { StorageDel = 0; /* * XXX: free it, its dead */ } else { if (StorageTmp && StorageTmp->mteObjectsEntryStatus == RS_CREATEANDGO) { StorageTmp->mteObjectsEntryStatus = RS_ACTIVE; } else if (StorageTmp && StorageTmp->mteObjectsEntryStatus == RS_CREATEANDWAIT) { StorageTmp->mteObjectsEntryStatus = RS_NOTINSERVICE; } } snmp_store_needed(NULL); break; } return SNMP_ERR_NOERROR; }