diff --git a/action.c b/action.c index f75a39de9cf..570dc793f04 100644 --- a/action.c +++ b/action.c @@ -443,6 +443,31 @@ int do_action(struct action* a, struct sip_msg* msg) ret=E_BUG; switch ((unsigned char)a->type){ + case ASSERT_T: + if (enable_asserts) { + /* if null expr => ignore if? */ + if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){ + v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0); + + ret=1; /*default is continue */ + + if (v<=0) { + ret=0; + + LM_CRIT("ASSERTION FAILED - %s\n", a->elem[1].u.string); + + if (abort_on_assert) { + abort(); + } else { + set_err_info(OSER_EC_ASSERT, OSER_EL_CRITIC, "assertion failed"); + set_err_reply(500, "server error"); + + run_error_route(msg,0); + } + } + } + } + break; case DROP_T: script_trace("core", "drop", msg, a->file, a->line) ; action_flags |= ACT_FL_DROP; diff --git a/cfg.lex b/cfg.lex index 3f69baf37ba..c0739a3294c 100644 --- a/cfg.lex +++ b/cfg.lex @@ -134,6 +134,7 @@ /* action keywords */ FORWARD forward +ASSERT "assert" DROP "drop" EXIT "exit" RETURN "return" @@ -280,6 +281,8 @@ SCRIPTVAR_START "$" /* config vars. */ DEBUG debug +ENABLE_ASSERTS enable_asserts +ABORT_ON_ASSERT abort_on_assert FORK fork LOGSTDERROR log_stderror LOGFACILITY log_facility @@ -449,6 +452,7 @@ IMPORTFILE "import_file" {EAT_ABLE} { count(); } {FORWARD} {count(); yylval.strval=yytext; return FORWARD; } +{ASSERT} {count(); yylval.strval=yytext; return ASSERT; } {DROP} { count(); yylval.strval=yytext; return DROP; } {EXIT} { count(); yylval.strval=yytext; return EXIT; } {RETURN} { count(); yylval.strval=yytext; return RETURN; } @@ -580,6 +584,8 @@ IMPORTFILE "import_file" {MYSELF} { count(); yylval.strval=yytext; return MYSELF; } {DEBUG} { count(); yylval.strval=yytext; return DEBUG; } +{ENABLE_ASSERTS} { count(); yylval.strval=yytext; return ENABLE_ASSERTS; } +{ABORT_ON_ASSERT} { count(); yylval.strval=yytext; return ABORT_ON_ASSERT; } {FORK} { count(); yylval.strval=yytext; return FORK; } {LOGSTDERROR} { yylval.strval=yytext; return LOGSTDERROR; } {LOGFACILITY} { yylval.strval=yytext; return LOGFACILITY; } diff --git a/cfg.y b/cfg.y index 3830b251f5b..ff22bbba5e9 100644 --- a/cfg.y +++ b/cfg.y @@ -221,6 +221,7 @@ extern char *finame; %token FORWARD %token SEND %token DROP +%token ASSERT %token EXIT %token RETURN %token LOG_TOK @@ -316,6 +317,8 @@ extern char *finame; /* config vars. */ %token DEBUG +%token ENABLE_ASSERTS +%token ABORT_ON_ASSERT %token FORK %token LOGSTDERROR %token LOGFACILITY @@ -658,6 +661,10 @@ assign_stm: DEBUG EQUAL snumber { *debug=$3; } | DEBUG EQUAL error { yyerror("number expected"); } + | ENABLE_ASSERTS EQUAL NUMBER { enable_asserts=$3; } + | ENABLE_ASSERTS EQUAL error { yyerror("boolean value expected"); } + | ABORT_ON_ASSERT EQUAL NUMBER { abort_on_assert=$3; } + | ABORT_ON_ASSERT EQUAL error { yyerror("boolean value expected"); } | FORK EQUAL NUMBER { dont_fork= !dont_fork ? ! $3:1; } | FORK EQUAL error { yyerror("boolean value expected"); } | LOGSTDERROR EQUAL NUMBER { if (!config_check) log_stderr=$3; } @@ -2530,6 +2537,7 @@ cmd: FORWARD LPAREN STRING RPAREN { mk_action2( $$, FORWARD_T, | SEND error { $$=0; yyerror("missing '(' or ')' ?"); } | SEND LPAREN error RPAREN { $$=0; yyerror("bad send" "argument"); } + | ASSERT LPAREN exp COMMA STRING RPAREN {mk_action2( $$, ASSERT_T, EXPR_ST, STRING_ST, $3, $5); } | DROP LPAREN RPAREN {mk_action2( $$, DROP_T,0, 0, 0, 0); } | DROP {mk_action2( $$, DROP_T,0, 0, 0, 0); } | EXIT LPAREN RPAREN {mk_action2( $$, EXIT_T,0, 0, 0, 0); } diff --git a/errinfo.h b/errinfo.h index 41d4ba85761..235e571ac8d 100644 --- a/errinfo.h +++ b/errinfo.h @@ -35,6 +35,7 @@ #define OSER_EC_PARSER 1 /*!< parse error */ #define OSER_EC_PMEMORY 2 /*!< private memory error */ #define OSER_EC_SMEMORY 3 /*!< share memory error */ +#define OSER_EC_ASSERT 4 /*!< assertion error */ #define OSER_EL_CRITIC 1 #define OSER_EL_HIGH 2 diff --git a/globals.h b/globals.h index 99a08e76b3d..184eb61943e 100644 --- a/globals.h +++ b/globals.h @@ -171,4 +171,7 @@ extern char *db_version_table; extern char *db_default_url; extern int disable_503_translation; + +extern int enable_asserts; +extern int abort_on_assert; #endif diff --git a/main.c b/main.c index e2f70b614ac..c3b6bb4b6f4 100644 --- a/main.c +++ b/main.c @@ -218,6 +218,10 @@ int sig_flag = 0; /* last signal received */ int dont_fork = 0; int no_daemon_mode = 0; +/* assertion statements in script. disabled by default */ +int enable_asserts = 0; +/* abort process on failed assertion. disabled by default */ +int abort_on_assert = 0; /* start by logging to stderr */ int log_stderr = 1; /* log facility (see syslog(3)) */ diff --git a/route_struct.c b/route_struct.c index ab422da7b38..9359ea44002 100644 --- a/route_struct.c +++ b/route_struct.c @@ -414,6 +414,9 @@ void print_action(struct action* t) case SEND_T: LM_DBG("send("); break; + case ASSERT_T: + LM_DBG("assert("); + break; case DROP_T: LM_DBG("drop("); break; diff --git a/route_struct.h b/route_struct.h index bc6d282186b..a9006abdfe2 100644 --- a/route_struct.h +++ b/route_struct.h @@ -61,7 +61,7 @@ enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O, DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O, EXPR_O, NUMBER_O, NUMBERV_O, STRINGV_O, RETCODE_O, SCRIPTVAR_O}; -enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, +enum { FORWARD_T=1, SEND_T, ASSERT_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, SET_PORT_T, SET_URI_T, IF_T, MODULE_T, SET_DEBUG_T, SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,