/** handles requests for the expExpressionTable table */ int expExpressionTable_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_request_info *request; netsnmp_table_request_info *tinfo; netsnmp_tdata_row *row; struct expExpression *entry; char expOwner[EXP_STR1_LEN+1]; char expName[ EXP_STR1_LEN+1]; long ret; DEBUGMSGTL(("disman:expr:mib", "Expression Table handler (%d)\n", reqinfo->mode)); switch (reqinfo->mode) { /* * Read-support (also covers GetNext requests) */ case MODE_GET: for (request = requests; request; request = request->next) { if (request->processed) continue; entry = (struct expExpression *) netsnmp_tdata_extract_entry(request); tinfo = netsnmp_extract_table_info(request); if (!entry || !(entry->flags & EXP_FLAG_VALID)) continue; switch (tinfo->colnum) { case COLUMN_EXPEXPRESSION: snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char*)entry->expExpression, strlen(entry->expExpression)); break; case COLUMN_EXPEXPRESSIONVALUETYPE: snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, entry->expValueType); break; case COLUMN_EXPEXPRESSIONCOMMENT: snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char*)entry->expComment, strlen(entry->expComment)); break; case COLUMN_EXPEXPRESSIONDELTAINTERVAL: snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, entry->expDeltaInterval); break; case COLUMN_EXPEXPRESSIONPREFIX: /* * XXX - Need to search expObjectTable for a suitable OID */ /* * Empty OIDs (len=0) are converted into .0.0 * by the SNMP library automatically :-( */ if ( entry->expPrefix_len ) { snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID, (u_char *) entry->expPrefix, entry->expPrefix_len*sizeof(oid)); } else { /* XXX - possibly not needed */ request->requestvb->type = ASN_OBJECT_ID; request->requestvb->val_len = 0; } break; case COLUMN_EXPEXPRESSIONERRORS: snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER, entry->expErrorCount); break; case COLUMN_EXPEXPRESSIONENTRYSTATUS: /* What would indicate 'notReady' ? */ ret = (entry->flags & EXP_FLAG_ACTIVE) ? RS_ACTIVE : RS_NOTINSERVICE; snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret); break; } } break; /* * Write-support */ case MODE_SET_RESERVE1: for (request = requests; request; request = request->next) { if (request->processed) continue; entry = (struct expExpression *) netsnmp_tdata_extract_entry(request); tinfo = netsnmp_extract_table_info(request); switch (tinfo->colnum) { case COLUMN_EXPEXPRESSION: ret = netsnmp_check_vb_type_and_max_size( request->requestvb, ASN_OCTET_STR, EXP_STR3_LEN); /* XXX - check new expression is syntactically valid */ if (ret != SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, request, ret); return SNMP_ERR_NOERROR; } break; case COLUMN_EXPEXPRESSIONVALUETYPE: ret = netsnmp_check_vb_int_range(request->requestvb, 1, 8); if (ret != SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, request, ret); return SNMP_ERR_NOERROR; } break; case COLUMN_EXPEXPRESSIONCOMMENT: ret = netsnmp_check_vb_type_and_max_size( request->requestvb, ASN_OCTET_STR, EXP_STR2_LEN); if (ret != SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, request, ret); return SNMP_ERR_NOERROR; } break; case COLUMN_EXPEXPRESSIONDELTAINTERVAL: ret = netsnmp_check_vb_int_range(request->requestvb, 0, 86400); if (ret != SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, request, ret); return SNMP_ERR_NOERROR; } break; case COLUMN_EXPEXPRESSIONENTRYSTATUS: ret = netsnmp_check_vb_rowstatus(request->requestvb, (entry ? RS_ACTIVE : RS_NONEXISTENT)); if (ret != SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, request, ret); return SNMP_ERR_NOERROR; } break; default: netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOTWRITABLE); return SNMP_ERR_NOERROR; } } break; case MODE_SET_RESERVE2: for (request = requests; request; request = request->next) { if (request->processed) continue; tinfo = netsnmp_extract_table_info(request); switch (tinfo->colnum) { case COLUMN_EXPEXPRESSIONENTRYSTATUS: switch (*request->requestvb->val.integer) { case RS_CREATEANDGO: case RS_CREATEANDWAIT: /* * Create an (empty) new row structure */ memset(expOwner, 0, sizeof(expOwner)); memcpy(expOwner, tinfo->indexes->val.string, tinfo->indexes->val_len); memset(expName, 0, sizeof(expName)); memcpy(expName, tinfo->indexes->next_variable->val.string, tinfo->indexes->next_variable->val_len); row = expExpression_createRow(expOwner, expName, 0); if (!row) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_RESOURCEUNAVAILABLE); return SNMP_ERR_NOERROR; } netsnmp_insert_tdata_row( request, row ); } } } break; case MODE_SET_FREE: for (request = requests; request; request = request->next) { if (request->processed) continue; tinfo = netsnmp_extract_table_info(request); switch (tinfo->colnum) { case COLUMN_EXPEXPRESSIONENTRYSTATUS: switch (*request->requestvb->val.integer) { case RS_CREATEANDGO: case RS_CREATEANDWAIT: /* * Tidy up after a failed row creation request */ entry = (struct expExpression *) netsnmp_tdata_extract_entry(request); if (entry && !(entry->flags & EXP_FLAG_VALID)) { row = (netsnmp_tdata_row *) netsnmp_tdata_extract_row(request); expExpression_removeEntry( row ); } } } } break; case MODE_SET_ACTION: for (request = requests; request; request = request->next) { if (request->processed) continue; tinfo = netsnmp_extract_table_info(request); entry = (struct expExpression *) netsnmp_tdata_extract_entry(request); if (!entry) { /* * New rows must be created via the RowStatus column */ netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOCREATION); /* or inconsistentName? */ return SNMP_ERR_NOERROR; } } break; case MODE_SET_UNDO: break; case MODE_SET_COMMIT: /* * All these assignments are "unfailable", so it's * (reasonably) safe to apply them in the Commit phase */ for (request = requests; request; request = request->next) { if (request->processed) continue; entry = (struct expExpression *) netsnmp_tdata_extract_entry(request); tinfo = netsnmp_extract_table_info(request); switch (tinfo->colnum) { case COLUMN_EXPEXPRESSION: memset(entry->expExpression, 0, EXP_STR3_LEN+1); memcpy(entry->expExpression, request->requestvb->val.string, request->requestvb->val_len); break; case COLUMN_EXPEXPRESSIONVALUETYPE: entry->expValueType = *request->requestvb->val.integer; break; case COLUMN_EXPEXPRESSIONCOMMENT: memset(entry->expComment, 0, EXP_STR2_LEN+1); memcpy(entry->expComment, request->requestvb->val.string, request->requestvb->val_len); break; case COLUMN_EXPEXPRESSIONDELTAINTERVAL: entry->expDeltaInterval = *request->requestvb->val.integer; break; case COLUMN_EXPEXPRESSIONENTRYSTATUS: switch (*request->requestvb->val.integer) { case RS_ACTIVE: entry->flags |= EXP_FLAG_ACTIVE; expExpression_enable( entry ); break; case RS_NOTINSERVICE: entry->flags &= ~EXP_FLAG_ACTIVE; expExpression_disable( entry ); break; case RS_CREATEANDGO: entry->flags |= EXP_FLAG_ACTIVE; entry->flags |= EXP_FLAG_VALID; entry->session = netsnmp_iquery_pdu_session(reqinfo->asp->pdu); expExpression_enable( entry ); break; case RS_CREATEANDWAIT: entry->flags |= EXP_FLAG_VALID; entry->session = netsnmp_iquery_pdu_session(reqinfo->asp->pdu); break; case RS_DESTROY: row = (netsnmp_tdata_row *) netsnmp_tdata_extract_row(request); expExpression_removeEntry(row); } } } break; } DEBUGMSGTL(("disman:expr:mib", "Expression Table handler - done \n")); return SNMP_ERR_NOERROR; }
void parse_expression(const char *token, char *line) { char buf[ SPRINT_MAX_LEN]; char ename[EXP_STR1_LEN+1]; oid name_buf[MAX_OID_LEN]; size_t name_len; char *cp, *cp2; struct expExpression *entry; struct expObject *object; netsnmp_session *sess = NULL; int type=EXPVALTYPE_COUNTER; int i=1; DEBUGMSGTL(("disman:expr:conf", "Parsing expression config... ")); memset(buf, 0, sizeof(buf)); memset(ename, 0, sizeof(ename)); for (cp = copy_nword(line, buf, SPRINT_MAX_LEN); ; cp = copy_nword(cp, buf, SPRINT_MAX_LEN)) { if (buf[0] == '-' ) { switch (buf[1]) { case 't': /* type */ switch (buf[2]) { case 'c': type = EXPVALTYPE_COUNTER; break; case 'u': type = EXPVALTYPE_UNSIGNED; break; case 't': type = EXPVALTYPE_TIMETICKS; break; case 'i': type = EXPVALTYPE_INTEGER; break; case 'a': type = EXPVALTYPE_IPADDRESS; break; case 's': type = EXPVALTYPE_STRING; break; case 'o': type = EXPVALTYPE_OID; break; case 'C': type = EXPVALTYPE_COUNTER64; break; } break; case 'u': /* user */ cp = copy_nword(cp, buf, SPRINT_MAX_LEN); sess = netsnmp_iquery_user_session(buf); break; } } else { break; } } memcpy(ename, buf, sizeof(ename)); /* cp = copy_nword(line, ename, sizeof(ename)); */ entry = expExpression_createEntry( "snmpd.conf", ename, 1 ); if (!entry) return; cp2 = entry->expExpression; while (cp && *cp) { /* * Copy everything that can't possibly be a MIB * object name into the expression field... */ /* XXX - TODO - Handle string literals */ if (!isalpha(*cp)) { *cp2++ = *cp++; continue; } /* * ... and copy the defined functions across as well * XXX - TODO */ /* * Anything else is presumably a MIB object (or instance). * Create an entry in the expObjectTable, and insert a * corresponding parameter in the expression itself. */ name_len = MAX_OID_LEN; cp = copy_nword(cp, buf, SPRINT_MAX_LEN); snmp_parse_oid( buf, name_buf, &name_len ); object = expObject_createEntry( "snmpd.conf", ename, i, 1 ); memcpy( object->expObjectID, name_buf, name_len*sizeof(oid)); object->expObjectID_len = name_len; object->flags |= EXP_OBJ_FLAG_VALID | EXP_OBJ_FLAG_ACTIVE | EXP_OBJ_FLAG_OWILD; /* * The first such object can also be used as the * expExpressionPrefix */ if ( i == 1 ) { memcpy( entry->expPrefix, name_buf, name_len*sizeof(oid)); entry->expPrefix_len = name_len; object->flags |= EXP_OBJ_FLAG_PREFIX; } sprintf(cp2, "$%d", i++); while (*cp2) cp2++; /* Skip over this parameter */ } if (sess) entry->session = sess; else entry->session = netsnmp_query_get_default_session(); entry->expDeltaInterval = 10; entry->expValueType = type; entry->flags |= EXP_FLAG_VALID | EXP_FLAG_ACTIVE; expExpression_enable( entry ); DEBUGMSG(("disman:expr:conf", "(%s, %s)\n", ename, entry->expExpression)); }