📄 expvalue.c
字号:
/* * DisMan Expression MIB: * Core implementation of expression evaluation */#include <net-snmp/net-snmp-config.h>#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-agent-includes.h>#include "disman/expr/expExpression.h"#include "disman/expr/expObject.h"#include "disman/expr/expValue.h"#include <ctype.h>void _expValue_setError( struct expExpression *exp, int reason, oid *suffix, size_t suffix_len, netsnmp_variable_list *var);#define ASN_PRIV_OPERATOR (ASN_PRIVATE | 0x0f)#define ASN_PRIV_FUNCTION (ASN_PRIVATE | 0x0e)int ops[128]; /* mapping from operator characters to numeric tokens (ordered by priority). */init_expValue(void){DEBUGMSGTL(("disman:expr:eval", "Init expValue")); /* Single-character operators */ ops['+'] = EXP_OPERATOR_ADD; ops['-'] = EXP_OPERATOR_SUBTRACT; ops['*'] = EXP_OPERATOR_MULTIPLY; ops['/'] = EXP_OPERATOR_DIVIDE; ops['%'] = EXP_OPERATOR_REMAINDER; ops['^'] = EXP_OPERATOR_BITXOR; ops['~'] = EXP_OPERATOR_BITNEGATE; ops['|'] = EXP_OPERATOR_BITOR; ops['&'] = EXP_OPERATOR_BITAND; ops['!'] = EXP_OPERATOR_NOT; ops['<'] = EXP_OPERATOR_LESS; ops['>'] = EXP_OPERATOR_GREAT; /* * Arbitrary offsets, chosen so * the three blocks don't overlap. */ /* "X=" operators */ ops['='+20] = EXP_OPERATOR_EQUAL; ops['!'+20] = EXP_OPERATOR_NOTEQ; ops['<'+20] = EXP_OPERATOR_LESSEQ; ops['>'+20] = EXP_OPERATOR_GREATEQ; /* "XX" operators */ ops['|'-30] = EXP_OPERATOR_OR; ops['&'-30] = EXP_OPERATOR_AND; ops['<'-30] = EXP_OPERATOR_LSHIFT; ops['>'-30] = EXP_OPERATOR_RSHIFT;} /* * Insert the value of the specified object parameter, * using the instance 'suffix' for wildcarded objects. */netsnmp_variable_list *_expValue_evalParam( netsnmp_variable_list *expIdx, int param, oid *suffix, size_t suffix_len ){ netsnmp_variable_list *var = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); struct expObject *obj; netsnmp_variable_list *val_var = NULL, *oval_var = NULL; /* values */ netsnmp_variable_list *dd_var = NULL, *odd_var = NULL; /* deltaDs */ netsnmp_variable_list *cond_var = NULL; /* conditionals */ int n; /* * Retrieve the expObject entry for the requested parameter. */ if ( !var || !expIdx || !expIdx->next_variable || !expIdx->next_variable->next_variable ) return NULL; *expIdx->next_variable->next_variable->val.integer = param; obj = (struct expObject *) netsnmp_tdata_row_entry( netsnmp_tdata_row_get_byidx( expObject_table_data, expIdx )); if (!obj) { /* * No such parameter configured for this expression */ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX ); var->type = ASN_NULL; return var; } if ( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE && obj->old_vars == NULL ) { /* * Can't calculate delta values until the second pass */ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_RESOURCE ); var->type = ASN_NULL; return var; } /* * For a wildcarded object, search for the matching suffix. */ val_var = obj->vars; if ( obj->flags & EXP_OBJ_FLAG_OWILD ) { if ( !suffix ) { /* * If there's no suffix to match against, throw an error. * An exact expression with a wildcarded object is invalid. * XXX - Or just use first entry? */ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX ); var->type = ASN_NULL; return var; } /* * Otherwise, we'll walk *all* wildcarded values in parallel. * This relies on the various varbind lists being set up with * exactly the same entries. A little extra preparation * during the data gathering simplifies things significantly! */ if ( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE ) oval_var = obj->old_vars; if ( obj->flags & EXP_OBJ_FLAG_DWILD ) { dd_var = obj->dvars; odd_var = obj->old_dvars; } if ( obj->flags & EXP_OBJ_FLAG_CWILD ) cond_var = obj->cvars; n = obj->expObjectID_len; while ( val_var ) { if ( snmp_oid_compare( val_var->name+n, val_var->name_length-n, suffix, suffix_len )) break; val_var = val_var->next_variable; if (oval_var) oval_var = oval_var->next_variable; if (dd_var) { dd_var = dd_var->next_variable; odd_var = odd_var->next_variable; } if (cond_var) cond_var = cond_var->next_variable; } } if (!val_var) { /* * No matching entry */ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX ); var->type = ASN_NULL; return var; } /* * Set up any non-wildcarded values - some * of which may be null. That's fine. */ if (!oval_var) oval_var = obj->old_vars; if (!dd_var) { dd_var = obj->dvars; odd_var = obj->old_dvars; } if (!cond_var) cond_var = obj->cvars; /* * ... and return the appropriate value. */ if (obj->expObjCond_len && (!cond_var || *cond_var->val.integer == 0)) { /* * expObjectConditional says no */ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX ); var->type = ASN_NULL; return var; } if (dd_var && odd_var && *dd_var->val.integer != *odd_var->val.integer) { /* * expObjectDeltaD says no */ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX ); var->type = ASN_NULL; return var; } /* * XXX - May need to check sysUpTime discontinuities * (unless this is handled earlier....) */ switch ( obj->expObjectSampleType ) { case EXPSAMPLETYPE_ABSOLUTE: snmp_clone_var( val_var, var ); break; case EXPSAMPLETYPE_DELTA: snmp_set_var_typed_integer( var, ASN_INTEGER /* or UNSIGNED? */, *val_var->val.integer - *oval_var->val.integer ); break; case EXPSAMPLETYPE_CHANGED: if ( val_var->val_len != oval_var->val_len ) n = 1; else if (memcmp( val_var->val.string, oval_var->val.string, val_var->val_len ) != 0 ) n = 1; else n = 0; snmp_set_var_typed_integer( var, ASN_UNSIGNED, n ); } return var;} /* * Utility routine to parse (and skip over) an integer constant */int_expParse_integer( char *start, char **end ) { int n; char *cp; n = atoi(start); for (cp=start; *cp; cp++) if (!isdigit(*cp)) break; *end = cp; return n;}netsnmp_variable_list *_expValue_evalOperator(netsnmp_variable_list *left, netsnmp_variable_list *op, netsnmp_variable_list *right) { int n; switch( *op->val.integer ) { case EXP_OPERATOR_ADD: n = *left->val.integer + *right->val.integer; break; case EXP_OPERATOR_SUBTRACT: n = *left->val.integer - *right->val.integer; break; case EXP_OPERATOR_MULTIPLY: n = *left->val.integer * *right->val.integer; break; case EXP_OPERATOR_DIVIDE: n = *left->val.integer / *right->val.integer; break; case EXP_OPERATOR_REMAINDER: n = *left->val.integer % *right->val.integer; break; case EXP_OPERATOR_BITXOR: n = *left->val.integer ^ *right->val.integer; break; case EXP_OPERATOR_BITNEGATE: n = 99; /* *left->val.integer ~ *right->val.integer; */ break; case EXP_OPERATOR_BITOR: n = *left->val.integer | *right->val.integer; break; case EXP_OPERATOR_BITAND: n = *left->val.integer & *right->val.integer; break; case EXP_OPERATOR_NOT: n = 99; /* *left->val.integer ! *right->val.integer; */ break; case EXP_OPERATOR_LESS: n = *left->val.integer < *right->val.integer; break; case EXP_OPERATOR_GREAT: n = *left->val.integer > *right->val.integer; break; case EXP_OPERATOR_EQUAL: n = *left->val.integer == *right->val.integer; break; case EXP_OPERATOR_NOTEQ: n = *left->val.integer != *right->val.integer; break; case EXP_OPERATOR_LESSEQ: n = *left->val.integer <= *right->val.integer; break; case EXP_OPERATOR_GREATEQ: n = *left->val.integer >= *right->val.integer; break; case EXP_OPERATOR_OR: n = *left->val.integer || *right->val.integer; break; case EXP_OPERATOR_AND: n = *left->val.integer && *right->val.integer; break; case EXP_OPERATOR_LSHIFT: n = *left->val.integer << *right->val.integer; break; case EXP_OPERATOR_RSHIFT: n = *left->val.integer >> *right->val.integer; break; break; default: left->next_variable = NULL; snmp_free_var(left); right->next_variable = NULL; snmp_free_var(right); snmp_set_var_typed_integer( op, ASN_INTEGER, EXPERRCODE_OPERATOR ); op->type = ASN_NULL; return op; } /* XXX */ left->next_variable = NULL; snmp_free_var(left); op->next_variable = NULL; snmp_free_var(op); snmp_set_var_typed_integer( right, ASN_INTEGER, n ); return right;}netsnmp_variable_list *_expValue_evalFunction(netsnmp_variable_list *func) { netsnmp_variable_list *params = func->next_variable; /* XXX */ params->next_variable = NULL; snmp_free_var(params); snmp_set_var_typed_integer( func, ASN_INTEGER, 99 ); return func;}netsnmp_variable_list *_expValue_evalExpr2(netsnmp_variable_list *exprAlDente);netsnmp_variable_list *_expValue_evalExpr( netsnmp_variable_list *expIdx, char *exprRaw, char **exprEnd, oid *suffix, size_t suffix_len ){ netsnmp_variable_list *exprAlDente = NULL; netsnmp_variable_list *vtail = NULL; char *cp1, *cp2, *cp3; netsnmp_variable_list *var = NULL; int i, n, level; int neg = 0; oid oid_buf[MAX_OID_LEN]; DEBUGMSGTL(("disman:expr:eval1", "Evaluating '%s'\n", exprRaw)); if (!expIdx || !exprRaw) return NULL; /* * The expression is evaluated in two stages. * First, we simplify ("parboil") the raw expression, * tokenizing it into a sequence of varbind values, inserting * object parameters, and (recursively) evaluating any * parenthesised sub-expressions or function arguments. */ for (cp1=exprRaw; cp1 && *cp1; ) { switch (*cp1) { case '$': /* * Locate the appropriate instance of the specified * parameter, and insert the corresponding value. */ n = _expParse_integer( cp1+1, &cp1 ); var = _expValue_evalParam( expIdx, n, suffix, suffix_len ); if ( var && var->type == ASN_NULL ) { DEBUGMSGTL(("disman:expr:eval", "Invalid parameter '%d'\n", n)); /* Note position of failure in expression */ var->data = (void *)(cp1 - exprRaw); snmp_free_var(exprAlDente); return var; } else { if (vtail) vtail->next_variable = var; else exprAlDente = var; vtail = var; var = NULL; } break; case '(': /* * Recursively evaluate the sub-expression */ var = _expValue_evalExpr( expIdx, cp1+1, &cp2, suffix, suffix_len ); if ( var && var->type == ASN_NULL ) { /* Adjust position of failure */ var->data = (void *)(cp1 - exprRaw + (int)var->data); return var; } else if (*cp2 != ')') { snmp_free_var(exprAlDente); DEBUGMSGTL(("disman:expr:eval", "Unbalanced parenthesis\n")); snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_PARENTHESIS ); var->type = ASN_NULL; var->data = (void *)(cp2 - exprRaw); return var; } else { if (vtail) vtail->next_variable = var; else exprAlDente = var; vtail = var; var = NULL; cp1 = cp2+1; /* Skip to end of sub-expression */ } break; case ')': case ',': /* * End of current (sub-)expression * Note the end-position, and evaluate * the parboiled list of tokens. */ *exprEnd = cp1; var = _expValue_evalExpr2( exprAlDente ); snmp_free_var(exprAlDente); return var;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -