4ac74c03 |
/*
* $Id$
|
7dd0b342 |
*
* Copyright (C) 2001-2003 Fhg Fokus
*
* This file is part of ser, a free SIP server.
*
* ser is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* For a license to use the ser software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* ser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
049f64c2 |
*
* History:
* ---------
|
3e8c3475 |
* 2003-02-28 scratchpad compatibility abandoned (jiri)
* 2003-01-29 removed scratchpad (jiri)
* 2003-03-19 fixed set* len calculation bug & simplified a little the code
|
b621d616 |
* (should be a little faster now) (andrei)
|
3e8c3475 |
* replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
* 2003-04-01 Added support for loose routing in forward (janakj)
* 2003-04-12 FORCE_RPORT_T added (andrei)
|
1d9f91d6 |
* 2003-04-22 strip_tail added (jiri)
|
6bfaa042 |
* 2003-10-02 added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
|
59653eb8 |
* 2003-10-29 added FORCE_TCP_ALIAS_T (andrei)
|
4ac74c03 |
*/
|
049f64c2 |
#include "comp_defs.h"
|
7dd0b342 |
|
4ac74c03 |
#include "action.h"
#include "config.h"
#include "error.h"
#include "dprint.h"
#include "proxy.h"
|
3e429f5c |
#include "forward.h"
#include "udp_server.h"
#include "route.h"
|
3881f12c |
#include "parser/msg_parser.h"
|
855c2e68 |
#include "parser/parse_uri.h"
|
104316b6 |
#include "ut.h"
|
3bf76e49 |
#include "sr_module.h"
|
dda9dab1 |
#include "mem/mem.h"
|
1400b772 |
#include "globals.h"
|
caf80ae6 |
#include "dset.h"
|
0c5da34b |
#ifdef USE_TCP
#include "tcp_server.h"
#endif
|
4ac74c03 |
|
a46cdb8c |
#include <sys/types.h>
#include <sys/socket.h>
|
4ac74c03 |
#include <netdb.h>
#include <stdlib.h>
|
63fa628f |
#include <netinet/in.h>
#include <arpa/inet.h>
|
e22bbdb8 |
#include <string.h>
|
63fa628f |
|
03150098 |
#ifdef DEBUG_DMALLOC
#include <dmalloc.h>
#endif
|
4ac74c03 |
|
7268726e |
/* ret= 0! if action -> end of list(e.g DROP),
> 0 to continue processing next actions
and <0 on error */
|
4ac74c03 |
int do_action(struct action* a, struct sip_msg* msg)
{
int ret;
|
f20a56a2 |
int v;
|
4e2fdd79 |
union sockaddr_union* to;
|
36ef0329 |
struct socket_info* send_sock;
|
4ac74c03 |
struct proxy_l* p;
|
7268726e |
char* tmp;
char *new_uri, *end, *crt;
int len;
|
45072d7a |
int user;
|
9de57c42 |
struct sip_uri uri, next_hop;
|
855c2e68 |
struct sip_uri* u;
|
5ada8f8a |
unsigned short port;
|
f2f969dd |
int proto;
|
4ac74c03 |
|
1400b772 |
/* reset the value of error to E_UNSPEC so avoid unknowledgable
functions to return with errror (status<0) and not setting it
leaving there previous error; cache the previous value though
for functions which want to process it */
prev_ser_error=ser_error;
ser_error=E_UNSPEC;
|
3e429f5c |
ret=E_BUG;
|
f2f969dd |
switch ((unsigned char)a->type){
|
4ac74c03 |
case DROP_T:
ret=0;
break;
case FORWARD_T:
|
f2f969dd |
#ifdef USE_TCP
case FORWARD_TCP_T:
|
8e807134 |
#endif
#ifdef USE_TLS
case FORWARD_TLS_T:
|
f2f969dd |
#endif
case FORWARD_UDP_T:
if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;
#ifdef USE_TCP
else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;
|
e9b02e8e |
#endif
#ifdef USE_TLS
else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
|
f2f969dd |
#endif
else proto=msg->rcv.proto;
|
5ada8f8a |
if (a->p1_type==URIHOST_ST){
/*parse uri*/
|
9de57c42 |
if (msg->dst_uri.len) {
ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop);
u = &next_hop;
} else {
ret = parse_sip_msg_uri(msg);
u = &msg->parsed_uri;
}
|
1400b772 |
if (ret<0) {
|
855c2e68 |
LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
" dropping packet\n");
|
5ada8f8a |
break;
}
|
9de57c42 |
|
5ada8f8a |
switch (a->p2_type){
case URIPORT_ST:
|
1baa06b5 |
port=u->port_no;
|
5ada8f8a |
break;
case NUMBER_ST:
port=a->p2.number;
break;
default:
LOG(L_CRIT, "BUG: do_action bad forward 2nd"
" param type (%d)\n", a->p2_type);
|
7f858173 |
ret=E_UNSPEC;
goto error_fwd_uri;
|
5ada8f8a |
}
|
f2e456c3 |
switch(u->proto){
case PROTO_NONE:
proto=PROTO_UDP;
break;
case PROTO_UDP:
#ifdef USE_TCP
case PROTO_TCP:
|
e9b02e8e |
#endif
#ifdef USE_TLS
case PROTO_TLS:
|
f2e456c3 |
#endif
proto=u->proto;
break;
default:
|
3f601bd0 |
LOG(L_ERR,"ERROR: do action: forward: bad uri"
" transport %d\n", u->proto);
|
f2e456c3 |
ret=E_BAD_PROTO;
goto error_fwd_uri;
}
|
3f601bd0 |
#ifdef USE_TLS
if (u->secure){
if (u->proto==PROTO_UDP){
LOG(L_ERR, "ERROR: do_action: forward: secure uri"
" incompatible with transport %d\n", u->proto);
ret=E_BAD_PROTO;
goto error_fwd_uri;
}
proto=PROTO_TLS;
}
#endif
|
5ada8f8a |
/* create a temporary proxy*/
|
d531a5d5 |
p=mk_proxy(&u->host, port, proto);
|
7f858173 |
if (p==0){
LOG(L_ERR, "ERROR: bad host name in uri,"
" dropping packet\n");
ret=E_BAD_ADDRESS;
goto error_fwd_uri;
}
|
f2f969dd |
ret=forward_request(msg, p, proto);
|
855c2e68 |
/*free_uri(&uri); -- no longer needed, in sip_msg*/
|
5ada8f8a |
free_proxy(p); /* frees only p content, not p itself */
|
e3dccdc9 |
pkg_free(p);
|
5ada8f8a |
if (ret>=0) ret=1;
}else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
|
f2f969dd |
ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);
|
5ada8f8a |
if (ret>=0) ret=1;
}else{
|
3e429f5c |
LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
a->p1_type, a->p2_type);
|
4ac74c03 |
ret=E_BUG;
}
break;
case SEND_T:
|
0c5da34b |
case SEND_TCP_T:
|
3e429f5c |
if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
a->p1_type, a->p2_type);
|
4ac74c03 |
ret=E_BUG;
break;
}
|
e3dccdc9 |
to=(union sockaddr_union*)
pkg_malloc(sizeof(union sockaddr_union));
|
4e2fdd79 |
if (to==0){
LOG(L_ERR, "ERROR: do_action: "
"memory allocation failure\n");
ret=E_OUT_OF_MEM;
break;
}
|
4ac74c03 |
p=(struct proxy_l*)a->p1.data;
if (p->ok==0){
if (p->host.h_addr_list[p->addr_idx+1])
p->addr_idx++;
|
5ada8f8a |
else
p->addr_idx=0;
|
4ac74c03 |
p->ok=1;
}
|
4e2fdd79 |
ret=hostent2su( to, &p->host, p->addr_idx,
|
6eacb2bc |
(p->port)?p->port:SIP_PORT );
|
4e2fdd79 |
if (ret==0){
p->tx++;
p->tx_bytes+=msg->len;
|
0c5da34b |
if (a->type==SEND_T){
/*udp*/
|
f2f969dd |
send_sock=get_send_socket(to, PROTO_UDP);
|
0c5da34b |
if (send_sock!=0){
|
049f64c2 |
ret=udp_send(send_sock, msg->buf, msg->len, to);
|
0c5da34b |
}else{
ret=-1;
}
}
#ifdef USE_TCP
else{
/*tcp*/
|
e9b02e8e |
ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0);
|
36ef0329 |
}
|
0c5da34b |
#endif
|
4e2fdd79 |
}
|
e3dccdc9 |
pkg_free(to);
|
4ac74c03 |
if (ret<0){
p->errors++;
p->ok=0;
}else ret=1;
break;
case LOG_T:
|
3e429f5c |
if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
a->p1_type, a->p2_type);
ret=E_BUG;
break;
}
LOG(a->p1.number, a->p2.string);
|
4ac74c03 |
ret=1;
break;
|
3881f12c |
|
caf80ae6 |
/* jku -- introduce a new branch */
case APPEND_BRANCH_T:
if ((a->p1_type!=STRING_ST)) {
LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
a->p1_type );
ret=E_BUG;
break;
}
ret=append_branch( msg, a->p1.string,
a->p1.string ? strlen(a->p1.string):0 );
break;
|
1f377e97 |
/* jku begin: is_length_greater_than */
case LEN_GT_T:
if (a->p1_type!=NUMBER_ST) {
LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
a->p1_type );
ret=E_BUG;
break;
}
/* DBG("XXX: message length %d, max %d\n",
msg->len, a->p1.number ); */
ret = msg->len >= a->p1.number ? 1 : -1;
break;
/* jku end: is_length_greater_than */
|
3881f12c |
/* jku - begin : flag processing */
case SETFLAG_T:
if (a->p1_type!=NUMBER_ST) {
LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
a->p1_type );
ret=E_BUG;
break;
}
if (!flag_in_range( a->p1.number )) {
ret=E_CFG;
break;
}
setflag( msg, a->p1.number );
ret=1;
break;
case RESETFLAG_T:
if (a->p1_type!=NUMBER_ST) {
LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
a->p1_type );
ret=E_BUG;
break;
}
if (!flag_in_range( a->p1.number )) {
ret=E_CFG;
break;
}
resetflag( msg, a->p1.number );
ret=1;
break;
case ISFLAGSET_T:
if (a->p1_type!=NUMBER_ST) {
LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
a->p1_type );
ret=E_BUG;
break;
}
if (!flag_in_range( a->p1.number )) {
ret=E_CFG;
break;
}
ret=isflagset( msg, a->p1.number );
break;
/* jku - end : flag processing */
|
4ac74c03 |
case ERROR_T:
|
3e429f5c |
if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
a->p1_type, a->p2_type);
ret=E_BUG;
break;
}
|
4ac74c03 |
LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
"not implemented yet\n", a->p1.string, a->p2.string);
ret=1;
break;
case ROUTE_T:
|
3e429f5c |
if (a->p1_type!=NUMBER_ST){
LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
a->p1_type);
ret=E_BUG;
break;
}
if ((a->p1.number>RT_NO)||(a->p1.number<0)){
LOG(L_ERR, "ERROR: invalid routing table number in"
|
b667b278 |
"route(%lu)\n", a->p1.number);
|
3e429f5c |
ret=E_CFG;
break;
}
|
f20a56a2 |
ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
|
4ac74c03 |
break;
case EXEC_T:
|
3e429f5c |
if (a->p1_type!=STRING_ST){
LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
a->p1_type);
ret=E_BUG;
break;
}
LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
|
4ac74c03 |
" using dumb version...\n", a->p1.string);
ret=system(a->p1.string);
if (ret!=0){
LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
}
ret=1;
break;
|
caf80ae6 |
case REVERT_URI_T:
if (msg->new_uri.s) {
pkg_free(msg->new_uri.s);
msg->new_uri.len=0;
msg->new_uri.s=0;
|
a6982b85 |
msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
|
caf80ae6 |
};
ret=1;
break;
|
7268726e |
case SET_HOST_T:
case SET_HOSTPORT_T:
case SET_USER_T:
case SET_USERPASS_T:
case SET_PORT_T:
case SET_URI_T:
|
1f377e97 |
case PREFIX_T:
case STRIP_T:
|
1d9f91d6 |
case STRIP_TAIL_T:
|
45072d7a |
user=0;
|
1d9f91d6 |
if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
|
1f377e97 |
if (a->p1_type!=NUMBER_ST) {
LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
a->p1_type);
break;
}
} else if (a->p1_type!=STRING_ST){
|
7268726e |
LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
a->p1_type);
ret=E_BUG;
break;
}
if (a->type==SET_URI_T){
|
f8d46776 |
if (msg->new_uri.s) {
|
b78959d0 |
pkg_free(msg->new_uri.s);
|
f8d46776 |
msg->new_uri.len=0;
|
903766ce |
}
|
a6982b85 |
msg->parsed_uri_ok=0;
|
7268726e |
len=strlen(a->p1.string);
|
b78959d0 |
msg->new_uri.s=pkg_malloc(len+1);
|
f8d46776 |
if (msg->new_uri.s==0){
|
45072d7a |
LOG(L_ERR, "ERROR: do_action: memory allocation"
" failure\n");
|
7268726e |
ret=E_OUT_OF_MEM;
break;
}
|
f8d46776 |
memcpy(msg->new_uri.s, a->p1.string, len);
msg->new_uri.s[len]=0;
msg->new_uri.len=len;
|
7268726e |
ret=1;
break;
}
|
f8d46776 |
if (msg->new_uri.s) {
tmp=msg->new_uri.s;
len=msg->new_uri.len;
}else{
tmp=msg->first_line.u.request.uri.s;
len=msg->first_line.u.request.uri.len;
}
if (parse_uri(tmp, len, &uri)<0){
|
45072d7a |
LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
" packet\n", tmp);
|
7268726e |
ret=E_UNSPEC;
break;
}
|
b78959d0 |
new_uri=pkg_malloc(MAX_URI_SIZE);
|
7268726e |
if (new_uri==0){
|
45072d7a |
LOG(L_ERR, "ERROR: do_action: memory allocation "
" failure\n");
|
7268726e |
ret=E_OUT_OF_MEM;
break;
}
end=new_uri+MAX_URI_SIZE;
crt=new_uri;
/* begin copying */
len=strlen("sip:"); if(crt+len>end) goto error_uri;
memcpy(crt,"sip:",len);crt+=len;
|
1f377e97 |
|
7268726e |
/* user */
|
1f377e97 |
/* prefix (-jiri) */
if (a->type==PREFIX_T) {
|
45072d7a |
tmp=a->p1.string;
|
7268726e |
len=strlen(tmp); if(crt+len>end) goto error_uri;
memcpy(crt,tmp,len);crt+=len;
|
b621d616 |
/* whatever we had before, with prefix we have username
now */
|
1f377e97 |
user=1;
}
if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
tmp=a->p1.string;
len=strlen(tmp);
} else if (a->type==STRIP_T) {
if (a->p1.number>uri.user.len) {
|
b621d616 |
LOG(L_WARN, "Error: too long strip asked; "
|
b667b278 |
" deleting username: %lu of <%.*s>\n",
|
b621d616 |
a->p1.number, uri.user.len, uri.user.s );
|
1f377e97 |
len=0;
} else if (a->p1.number==uri.user.len) {
len=0;
} else {
tmp=uri.user.s + a->p1.number;
len=uri.user.len - a->p1.number;
}
|
1d9f91d6 |
} else if (a->type==STRIP_TAIL_T) {
if (a->p1.number>uri.user.len) {
LOG(L_WARN, "WARNING: too long strip_tail asked; "
|
b667b278 |
" deleting username: %lu of <%.*s>\n",
|
1d9f91d6 |
a->p1.number, uri.user.len, uri.user.s );
len=0;
} else if (a->p1.number==uri.user.len) {
len=0;
} else {
tmp=uri.user.s;
len=uri.user.len - a->p1.number;
}
|
1f377e97 |
} else {
tmp=uri.user.s;
len=uri.user.len;
}
if (len){
if(crt+len>end) goto error_uri;
memcpy(crt,tmp,len);crt+=len;
|
45072d7a |
user=1; /* we have an user field so mark it */
|
7268726e |
}
|
1f377e97 |
|
7268726e |
if (a->type==SET_USERPASS_T) tmp=0;
|
f8d46776 |
else tmp=uri.passwd.s;
|
7268726e |
/* passwd */
if (tmp){
|
b621d616 |
len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
*crt=':'; crt++;
|
7268726e |
memcpy(crt,tmp,len);crt+=len;
}
/* host */
|
45072d7a |
if (user || tmp){ /* add @ */
|
b621d616 |
if(crt+1>end) goto error_uri;
*crt='@'; crt++;
|
45072d7a |
}
|
a6982b85 |
if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
|
45072d7a |
tmp=a->p1.string;
|
a6982b85 |
if (tmp) len = strlen(tmp);
|
b621d616 |
else len=0;
|
a6982b85 |
} else {
|
f8d46776 |
tmp=uri.host.s;
|
a6982b85 |
len = uri.host.len;
}
|
7268726e |
if (tmp){
|
a6982b85 |
if(crt+len>end) goto error_uri;
|
7268726e |
memcpy(crt,tmp,len);crt+=len;
}
/* port */
if (a->type==SET_HOSTPORT_T) tmp=0;
|
a6982b85 |
else if (a->type==SET_PORT_T) {
tmp=a->p1.string;
if (tmp) len = strlen(tmp);
|
b621d616 |
else len = 0;
|
a6982b85 |
} else {
tmp=uri.port.s;
len = uri.port.len;
}
|
7268726e |
if (tmp){
|
b621d616 |
if(crt+len+1>end) goto error_uri;
*crt=':'; crt++;
|
7268726e |
memcpy(crt,tmp,len);crt+=len;
}
/* params */
|
f8d46776 |
tmp=uri.params.s;
|
7268726e |
if (tmp){
|
b621d616 |
len=uri.params.len; if(crt+len+1>end) goto error_uri;
*crt=';'; crt++;
|
7268726e |
memcpy(crt,tmp,len);crt+=len;
}
/* headers */
|
f8d46776 |
tmp=uri.headers.s;
|
7268726e |
if (tmp){
|
b621d616 |
len=uri.headers.len; if(crt+len+1>end) goto error_uri;
*crt='?'; crt++;
|
7268726e |
memcpy(crt,tmp,len);crt+=len;
}
*crt=0; /* null terminate the thing */
/* copy it to the msg */
|
b78959d0 |
if (msg->new_uri.s) pkg_free(msg->new_uri.s);
|
f8d46776 |
msg->new_uri.s=new_uri;
msg->new_uri.len=crt-new_uri;
|
a6982b85 |
msg->parsed_uri_ok=0;
|
7268726e |
ret=1;
break;
|
f20a56a2 |
case IF_T:
/* if null expr => ignore if? */
if ((a->p1_type==EXPR_ST)&&a->p1.data){
v=eval_expr((struct expr*)a->p1.data, msg);
if (v<0){
|
a1041efe |
if (v==EXPR_DROP){ /* hack to quit on DROP*/
ret=0;
break;
}else{
LOG(L_WARN,"WARNING: do_action:"
"error in expression\n");
}
|
f20a56a2 |
}
|
a1041efe |
|
9e973a63 |
ret=1; /*default is continue */
|
9598488f |
if (v>0) {
|
f20a56a2 |
if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
ret=run_actions((struct action*)a->p2.data, msg);
}
}else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
ret=run_actions((struct action*)a->p3.data, msg);
}
}
break;
|
3bf76e49 |
case MODULE_T:
|
21f03122 |
if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
|
34fd2612 |
ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
(char*)a->p3.data);
|
3bf76e49 |
}else{
LOG(L_CRIT,"BUG: do_action: bad module call\n");
}
break;
|
3e8c3475 |
case FORCE_RPORT_T:
msg->msg_flags|=FL_FORCE_RPORT;
ret=1; /* continue processing */
break;
|
6bfaa042 |
case SET_ADV_ADDR_T:
if (a->p1_type!=STR_ST){
LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
"type %d\n", a->p1_type);
ret=E_BUG;
break;
}
msg->set_global_address=*((str*)a->p1.data);
ret=1; /* continue processing */
break;
case SET_ADV_PORT_T:
if (a->p1_type!=STR_ST){
LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
"type %d\n", a->p1_type);
ret=E_BUG;
break;
}
msg->set_global_port=*((str*)a->p1.data);
ret=1; /* continue processing */
break;
|
59653eb8 |
#ifdef USE_TCP
case FORCE_TCP_ALIAS_T:
if ( msg->rcv.proto==PROTO_TCP
#ifdef USE_TLS
|| msg->rcv.proto==PROTO_TLS
#endif
){
if (a->p1_type==NOSUBTYPE) port=msg->via1->port;
else if (a->p1_type==NUMBER_ST) port=(int)a->p1.number;
else{
LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
" port type %d\n", a->p1_type);
ret=E_BUG;
break;
}
if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
msg->rcv.proto)!=0){
LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
ret=E_UNSPEC;
break;
}
}
#endif
ret=1; /* continue processing */
break;
|
4ac74c03 |
default:
LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
}
|
e22bbdb8 |
/*skip:*/
|
4ac74c03 |
return ret;
|
7268726e |
error_uri:
LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
|
764df2b2 |
if (new_uri) pkg_free(new_uri);
|
7268726e |
return E_UNSPEC;
|
7f858173 |
error_fwd_uri:
|
855c2e68 |
/*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
|
7f858173 |
return ret;
|
4ac74c03 |
}
|
f20a56a2 |
/* returns: 0, or 1 on success, <0 on error */
/* (0 if drop or break encountered, 1 if not ) */
|
4ac74c03 |
int run_actions(struct action* a, struct sip_msg* msg)
{
struct action* t;
|
e22bbdb8 |
int ret=E_UNSPEC;
|
3e429f5c |
static int rec_lev=0;
|
4bd1673d |
struct sr_module *mod;
|
3e429f5c |
rec_lev++;
if (rec_lev>ROUTE_MAX_REC_LEV){
LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
" giving up!\n", rec_lev);
ret=E_UNSPEC;
goto error;
}
|
4ac74c03 |
if (a==0){
|
ea6721d7 |
LOG(L_ERR, "WARNING: run_actions: null action list (rec_level=%d)\n",
rec_lev);
|
4ac74c03 |
ret=0;
}
for (t=a; t!=0; t=t->next){
ret=do_action(t, msg);
if(ret==0) break;
|
5ada8f8a |
/* ignore errors */
/*else if (ret<0){ ret=-1; goto error; }*/
|
4ac74c03 |
}
|
3e429f5c |
rec_lev--;
|
4bd1673d |
/* process module onbreak handlers if present */
if (rec_lev==0 && ret==0)
for (mod=modules;mod;mod=mod->next)
if (mod->exports && mod->exports->onbreak_f) {
mod->exports->onbreak_f( msg );
DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
}
|
f20a56a2 |
return ret;
|
3e429f5c |
|
4ac74c03 |
error:
|
3e429f5c |
rec_lev--;
|
4ac74c03 |
return ret;
}
|