int write_expExpressionEntryStatus(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 expExpressionTable_data *StorageTmp = NULL; static struct expExpressionTable_data *StorageNew, *StorageDel; size_t newlen = name_len - (sizeof(expExpressionTable_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(expExpressionTableStorage, NULL, &name[sizeof(expExpressionTable_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 expExpressionEntryStatus not ASN_INTEGER\n"); return SNMP_ERR_WRONGTYPE; } 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; } if (StorageTmp->expExpressionEntryStatus == RS_ACTIVE && set_value != RS_DESTROY) { /* * "Once made active an entry may not be modified except to * delete it." XXX: doesn't this in fact apply to ALL * columns of the table and not just this one? */ return SNMP_ERR_INCONSISTENTVALUE; } if (StorageTmp->storageType != ST_NONVOLATILE) return SNMP_ERR_NOTWRITABLE; } 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); /* expExpressionOwner */ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* expExpressionName */ if (header_complex_parse_oid (& (name [sizeof(expExpressionTable_variables_oid) / sizeof(oid) + 2]), newlen, vars) != SNMPERR_SUCCESS) { /* * XXX: free, zero vars */ return SNMP_ERR_INCONSISTENTNAME; } vp = vars; StorageNew = create_expExpressionTable_data(); StorageNew->expExpressionOwner = malloc(vp->val_len + 1); memcpy(StorageNew->expExpressionOwner, vp->val.string, vp->val_len); StorageNew->expExpressionOwner[vp->val_len] = '\0'; StorageNew->expExpressionOwnerLen = vp->val_len; vp = vp->next_variable; StorageNew->expExpressionName = malloc(vp->val_len + 1); memcpy(StorageNew->expExpressionName, vp->val.string, vp->val_len); StorageNew->expExpressionName[vp->val_len] = '\0'; StorageNew->expExpressionNameLen = vp->val_len; vp = vp->next_variable; StorageNew->expExpressionEntryStatus = set_value; } 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) expExpressionTable_add(StorageNew); /* * XXX: ack, and if it is NULL? */ } else if (set_value != RS_DESTROY) { /* * set the flag? */ old_value = StorageTmp->expExpressionEntryStatus; StorageTmp->expExpressionEntryStatus = *((long *) var_val); } else { /* * destroy... extract it for now */ hciptr = header_complex_find_entry(expExpressionTableStorage, StorageTmp); StorageDel = header_complex_extract_entry(&expExpressionTableStorage, 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(expExpressionTableStorage, StorageTmp); StorageDel = header_complex_extract_entry(&expExpressionTableStorage, hciptr); /* * XXX: free it */ } else if (StorageDel != NULL) { /* * row deletion, so add it again */ expExpressionTable_add(StorageDel); } else { StorageTmp->expExpressionEntryStatus = 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->expExpressionEntryStatus == RS_CREATEANDGO) { StorageTmp->expExpressionEntryStatus = RS_ACTIVE; } else if (StorageTmp && StorageTmp->expExpressionEntryStatus == RS_CREATEANDWAIT) { StorageTmp->expExpressionEntryStatus = RS_NOTINSERVICE; } } if (StorageTmp && StorageTmp->expExpressionEntryStatus == RS_ACTIVE && !StorageTmp->have_copied_auth_info) { netsnmp_agent_session *asp = netsnmp_get_current_agent_session(); netsnmp_pdu *pdu = NULL; if (!asp) { snmp_log(LOG_ERR, "snmpTriggerTable: can't get master session for authentication params\n"); } else { pdu = asp->orig_pdu; if (!pdu) { snmp_log(LOG_ERR, "snmpTriggerTable: can't get master pdu for authentication params\n"); } } if (pdu) { DEBUGMSGTL(("expExpressionTest", "copying PDU auth info\n")); StorageTmp->pdu_version = pdu->version; StorageTmp->pdu_securityModel = pdu->securityModel; StorageTmp->pdu_securityLevel = pdu->securityLevel; StorageTmp->pdu_tDomain = pdu->tDomain; StorageTmp->pdu_tDomainLen = pdu->tDomainLen; if (pdu->transport_data != NULL) { StorageTmp->pdu_transport = malloc(pdu->transport_data_length); memcpy(StorageTmp->pdu_transport, pdu->transport_data, pdu->transport_data_length); } StorageTmp->pdu_transportLen = pdu->transport_data_length; if (pdu->community) { StorageTmp->pdu_community = calloc(1, pdu->community_len + 1); memcpy(StorageTmp->pdu_community, pdu->community, pdu->community_len); StorageTmp->pdu_community_len = pdu->community_len; } else { StorageTmp->pdu_community = NULL; StorageTmp->pdu_community_len = 0; } if (pdu->securityName) { StorageTmp->pdu_securityName = calloc(1, pdu->securityNameLen + 1); memcpy(StorageTmp->pdu_securityName, pdu->securityName, pdu->securityNameLen); StorageTmp->pdu_securityNameLen = pdu->securityNameLen; } else { StorageTmp->pdu_securityName = NULL; StorageTmp->pdu_securityNameLen = 0; } StorageTmp->have_copied_auth_info = 1; } } snmp_store_needed(NULL); break; } return SNMP_ERR_NOERROR; }
/** implements the old_api handler */ int netsnmp_old_api_helper(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { #if MIB_CLIENTS_ARE_EVIL oid save[MAX_OID_LEN]; size_t savelen = 0; #endif struct variable compat_var, *cvp = &compat_var; int exact = 1; int status; struct variable *vp; netsnmp_old_api_cache *cacheptr; netsnmp_agent_session *oldasp = NULL; u_char *access = NULL; WriteMethod *write_method = NULL; size_t len; size_t tmp_len; oid tmp_name[MAX_OID_LEN]; vp = (struct variable *) handler->myvoid; /* * create old variable structure with right information */ memcpy(cvp->name, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid)); cvp->namelen = reginfo->rootoid_len; cvp->type = vp->type; cvp->magic = vp->magic; cvp->acl = vp->acl; cvp->findVar = vp->findVar; switch (reqinfo->mode) { case MODE_GETNEXT: case MODE_GETBULK: exact = 0; } for (; requests; requests = requests->next) { #if MIB_CLIENTS_ARE_EVIL savelen = requests->requestvb->name_length; memcpy(save, requests->requestvb->name, savelen * sizeof(oid)); #endif switch (reqinfo->mode) { case MODE_GET: case MODE_GETNEXT: #ifndef NETSNMP_NO_WRITE_SUPPORT case MODE_SET_RESERVE1: #endif /* !NETSNMP_NO_WRITE_SUPPORT */ /* * Actually call the old mib-module function */ if (vp && vp->findVar) { memcpy(tmp_name, requests->requestvb->name, requests->requestvb->name_length*sizeof(oid)); tmp_len = requests->requestvb->name_length; access = (*(vp->findVar)) (cvp, tmp_name, &tmp_len, exact, &len, &write_method); snmp_set_var_objid( requests->requestvb, tmp_name, tmp_len ); } else access = NULL; #ifdef WWW_FIX if (IS_DELEGATED(cvp->type)) { add_method = (AddVarMethod *) statP; requests->delayed = 1; have_delegated = 1; continue; /* WWW: This may not get to the right place */ } #endif /* * WWW: end range checking */ if (access) { /* * result returned */ #ifndef NETSNMP_NO_WRITE_SUPPORT if (reqinfo->mode != MODE_SET_RESERVE1) #endif /* !NETSNMP_NO_WRITE_SUPPORT */ snmp_set_var_typed_value(requests->requestvb, cvp->type, access, len); } else { /* * no result returned */ #if MIB_CLIENTS_ARE_EVIL if (access == NULL) { if (netsnmp_oid_equals(requests->requestvb->name, requests->requestvb->name_length, save, savelen) != 0) { DEBUGMSGTL(("old_api", "evil_client: %s\n", reginfo->handlerName)); memcpy(requests->requestvb->name, save, savelen * sizeof(oid)); requests->requestvb->name_length = savelen; } } #endif } /* * AAA: fall through for everything that is a set (see BBB) */ #ifndef NETSNMP_NO_WRITE_SUPPORT if (reqinfo->mode != MODE_SET_RESERVE1) #endif /* !NETSNMP_NO_WRITE_SUPPORT */ break; cacheptr = SNMP_MALLOC_TYPEDEF(netsnmp_old_api_cache); if (!cacheptr) return netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE); cacheptr->data = access; cacheptr->write_method = write_method; write_method = NULL; netsnmp_request_add_list_data(requests, netsnmp_create_data_list (OLD_API_NAME, cacheptr, &free_wrapper)); /* * BBB: fall through for everything that is a set (see AAA) */ default: /* * WWW: explicitly list the SET conditions */ /* * (the rest of the) SET contions */ cacheptr = (netsnmp_old_api_cache *) netsnmp_request_get_list_data(requests, OLD_API_NAME); if (cacheptr == NULL || cacheptr->write_method == NULL) { /* * WWW: try to set ourselves if possible? */ return netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_NOTWRITABLE); } oldasp = netsnmp_get_current_agent_session(); set_current_agent_session(reqinfo->asp); status = (*(cacheptr->write_method)) (reqinfo->mode, requests->requestvb->val. string, requests->requestvb->type, requests->requestvb->val_len, cacheptr->data, requests->requestvb->name, requests->requestvb-> name_length); set_current_agent_session(oldasp); if (status != SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, requests, status); } /* * clean up is done by the automatic freeing of the * cache stored in the request. */ break; } } return SNMP_ERR_NOERROR; }