diff --git a/action.c b/action.c index 4cb5feec900..dec4a5eecdf 100644 --- a/action.c +++ b/action.c @@ -58,6 +58,7 @@ #include "parser/parse_uri.h" #include "ut.h" #include "sr_module.h" +#include "socket_info.h" #include "mem/mem.h" #include "globals.h" #include "dset.h" @@ -376,6 +377,48 @@ static int do_action_set_adv_port(struct sip_msg *msg, struct action *a) return ret; } +static int do_action_set_force_send_address(struct sip_msg *msg, struct action *a) +{ + str addr; + struct hostent* he; + struct ip_addr ip; + struct socket_info* si; + int ret = 1; /* continue processing */ + + if (a->elem[0].type != STR_ST) { + report_programming_bug("force_send_address type %d", a->elem[0].type); + ret = E_BUG; + goto out; + } + + if (pv_printf_s(msg, (pv_elem_t *)a->elem[0].u.data, &addr) != 0 + || addr.len <= 0) { + LM_WARN("cannot get string for value (%s:%d)\n",a->file, a->line); + ret = E_BUG; + goto out; + } + + LM_DBG("setting force send address = [%.*s]\n", addr.len, addr.s); + + he = resolvehost(addr.s, 0); + if (he == 0) { + LM_ERR("could not resolve %.*s\n", addr.len, addr.s); + ret = E_BAD_ADDRESS; + goto out; + } + hostent2ip_addr(&ip, he, 0); + si = find_si(&ip, 0, 0); + if (si == NULL) { + LM_ERR("bad force send address: %.*s (opensips doesn't listen on it)\n", addr.len, addr.s); + ret = E_BAD_ADDRESS; + goto out; + } + msg->force_send_socket = si; + +out: + return ret; +} + #define should_skip_updating(action_type) \ (action_type == IF_T || action_type == ROUTE_T || \ action_type == WHILE_T || action_type == FOR_EACH_T) @@ -1905,6 +1948,16 @@ int do_action(struct action* a, struct sip_msg* msg) msg->force_send_socket=(struct socket_info*)a->elem[0].u.data; ret=1; /* continue processing */ break; + case FORCE_SEND_ADDRESS_T: + script_trace("core", "force_send_address", msg, a->file, a->line) ; + if (a->elem[0].type!=STR_ST){ + LM_ALERT("BUG in force_send_address argument" + " type: %d\n", a->elem[0].type); + ret=E_BUG; + break; + } + ret = do_action_set_force_send_address(msg, a); + break; case SERIALIZE_BRANCHES_T: script_trace("core", "serialize_branches", msg, a->file, a->line) ; if (a->elem[0].type!=NUMBER_ST){ diff --git a/cfg.lex b/cfg.lex index 3f69baf37ba..a615a118942 100644 --- a/cfg.lex +++ b/cfg.lex @@ -191,6 +191,7 @@ IN "in" SET_ADV_ADDRESS "set_advertised_address" SET_ADV_PORT "set_advertised_port" FORCE_SEND_SOCKET "force_send_socket" +FORCE_SEND_ADDRESS "force_send_address" SERIALIZE_BRANCHES "serialize_branches" NEXT_BRANCHES "next_branches" USE_BLACKLIST "use_blacklist" @@ -523,6 +524,8 @@ IMPORTFILE "import_file" return SET_ADV_PORT; } {FORCE_SEND_SOCKET} { count(); yylval.strval=yytext; return FORCE_SEND_SOCKET; } +{FORCE_SEND_ADDRESS} { count(); yylval.strval=yytext; + return FORCE_SEND_ADDRESS; } {SERIALIZE_BRANCHES} { count(); yylval.strval=yytext; return SERIALIZE_BRANCHES; } {NEXT_BRANCHES} { count(); yylval.strval=yytext; diff --git a/cfg.y b/cfg.y index b969ce08824..f06db28368a 100644 --- a/cfg.y +++ b/cfg.y @@ -265,6 +265,7 @@ extern char *finame; %token SET_ADV_ADDRESS %token SET_ADV_PORT %token FORCE_SEND_SOCKET +%token FORCE_SEND_ADDRESS %token SERIALIZE_BRANCHES %token NEXT_BRANCHES %token USE_BLACKLIST @@ -2912,6 +2913,13 @@ cmd: FORWARD LPAREN STRING RPAREN { mk_action2( $$, FORWARD_T, " [proto:]host[:port] expected"); } | FORCE_SEND_SOCKET error {$$=0; yyerror("missing '(' or ')' ?"); } + | FORCE_SEND_ADDRESS LPAREN listen_id RPAREN { + mk_action2( $$, FORCE_SEND_ADDRESS_T, STR_ST, + 0, $3, 0); + } + | FORCE_SEND_ADDRESS LPAREN error RPAREN { $$=0; yyerror("bad argument, " + "string expected"); } + | FORCE_SEND_ADDRESS error {$$=0; yyerror("missing '(' or ')' ?"); } | SERIALIZE_BRANCHES LPAREN NUMBER RPAREN { mk_action2( $$, SERIALIZE_BRANCHES_T, NUMBER_ST, 0, (void*)(long)$3, 0); diff --git a/route.c b/route.c index 199be48bc7c..68e1f732ec4 100644 --- a/route.c +++ b/route.c @@ -493,6 +493,22 @@ static int fix_actions(struct action* a) t->elem[0].u.data=si; t->elem[0].type=SOCKETINFO_ST; break; + case FORCE_SEND_ADDRESS_T: + s.s = (char *)t->elem[0].u.data; + if (s.s == NULL) { + LM_ERR("null param in force_send_address\n"); + ret = E_BUG; + goto error; + } + s.len = strlen(s.s); + if (pv_parse_format(&s, &model) || model == NULL) { + LM_ERR("wrong format for [%.*s] address param!\n", + t->elem[1].u.s.len, t->elem[1].u.s.s); + ret = E_BUG; + goto error; + } + t->elem[0].u.data = (void *)model; + break; case SET_DEBUG_T: if (t->elem[0].type==NOSUBTYPE) break; diff --git a/route_struct.c b/route_struct.c index ab422da7b38..22a2156e952 100644 --- a/route_struct.c +++ b/route_struct.c @@ -516,6 +516,9 @@ void print_action(struct action* t) case FORCE_SEND_SOCKET_T: LM_DBG("force_send_socket"); break; + case FORCE_SEND_ADDRESS_T: + LM_DBG("force_send_address"); + break; case RETURN_T: LM_DBG("return("); break; diff --git a/route_struct.h b/route_struct.h index bc6d282186b..bde9040fddb 100644 --- a/route_struct.h +++ b/route_struct.h @@ -77,6 +77,7 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, SET_ADV_PORT_T, FORCE_TCP_ALIAS_T, FORCE_SEND_SOCKET_T, + FORCE_SEND_ADDRESS_T, SERIALIZE_BRANCHES_T, NEXT_BRANCHES_T, RETURN_T,