- added suuport for setting the source address and port in the sip requests
[sip-router] / action.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 Fhg Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  * History:
28  * ---------
29  *  2003-02-28  scratchpad compatibility abandoned (jiri)
30  *  2003-01-29  removed scratchpad (jiri)
31  *  2003-03-19  fixed set* len calculation bug & simplified a little the code
32  *              (should be a little faster now) (andrei)
33  *              replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
34  *  2003-04-01  Added support for loose routing in forward (janakj)
35  *  2003-04-12  FORCE_RPORT_T added (andrei)
36  *  2003-04-22  strip_tail added (jiri)
37  *  2003-10-02  added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
38  */
39
40
41 #include "comp_defs.h"
42
43 #include "action.h"
44 #include "config.h"
45 #include "error.h"
46 #include "dprint.h"
47 #include "proxy.h"
48 #include "forward.h"
49 #include "udp_server.h"
50 #include "route.h"
51 #include "parser/msg_parser.h"
52 #include "parser/parse_uri.h"
53 #include "ut.h"
54 #include "sr_module.h"
55 #include "mem/mem.h"
56 #include "globals.h"
57 #include "dset.h"
58 #ifdef USE_TCP
59 #include "tcp_server.h"
60 #endif
61
62 #include <sys/types.h>
63 #include <sys/socket.h>
64 #include <netdb.h>
65 #include <stdlib.h>
66 #include <netinet/in.h>
67 #include <arpa/inet.h>
68 #include <string.h>
69
70 #ifdef DEBUG_DMALLOC
71 #include <dmalloc.h>
72 #endif
73
74
75 /* ret= 0! if action -> end of list(e.g DROP), 
76       > 0 to continue processing next actions
77    and <0 on error */
78 int do_action(struct action* a, struct sip_msg* msg)
79 {
80         int ret;
81         int v;
82         union sockaddr_union* to;
83         struct socket_info* send_sock;
84         struct proxy_l* p;
85         char* tmp;
86         char *new_uri, *end, *crt;
87         int len;
88         int user;
89         struct sip_uri uri, next_hop;
90         struct sip_uri* u;
91         unsigned short port;
92         int proto;
93
94         /* reset the value of error to E_UNSPEC so avoid unknowledgable
95            functions to return with errror (status<0) and not setting it
96            leaving there previous error; cache the previous value though
97            for functions which want to process it */
98         prev_ser_error=ser_error;
99         ser_error=E_UNSPEC;
100
101         ret=E_BUG;
102         switch ((unsigned char)a->type){
103                 case DROP_T:
104                                 ret=0;
105                         break;
106                 case FORWARD_T:
107 #ifdef USE_TCP
108                 case FORWARD_TCP_T:
109 #endif
110 #ifdef USE_TLS
111                 case FORWARD_TLS_T:
112 #endif
113                 case FORWARD_UDP_T:
114
115                         if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;
116 #ifdef USE_TCP
117                         else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;
118 #endif
119 #ifdef USE_TLS
120                         else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
121 #endif
122                         else proto=msg->rcv.proto;
123                         if (a->p1_type==URIHOST_ST){
124                                 /*parse uri*/
125
126                                 if (msg->dst_uri.len) {
127                                         ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop);
128                                         u = &next_hop;
129                                 } else {
130                                         ret = parse_sip_msg_uri(msg);
131                                         u = &msg->parsed_uri;
132                                 }
133
134                                 if (ret<0) {
135                                         LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
136                                                                 " dropping packet\n");
137                                         break;
138                                 }
139                                 
140                                 switch (a->p2_type){
141                                         case URIPORT_ST:
142                                                                         port=u->port_no;
143                                                                         break;
144                                         case NUMBER_ST:
145                                                                         port=a->p2.number;
146                                                                         break;
147                                         default:
148                                                         LOG(L_CRIT, "BUG: do_action bad forward 2nd"
149                                                                                 " param type (%d)\n", a->p2_type);
150                                                         ret=E_UNSPEC;
151                                                         goto error_fwd_uri;
152                                 }
153                                 switch(u->proto){
154                                         case PROTO_NONE:
155                                                 proto=PROTO_UDP;
156                                                 break;
157                                         case PROTO_UDP:
158 #ifdef USE_TCP
159                                         case PROTO_TCP:
160 #endif
161 #ifdef USE_TLS
162                                         case PROTO_TLS:
163 #endif
164                                                 proto=u->proto;
165                                                 break;
166                                         default:
167                                                 LOG(L_ERR,"ERROR: do action: forward: bad uri"
168                                                                 " transport %d\n", u->proto);
169                                                 ret=E_BAD_PROTO;
170                                                 goto error_fwd_uri;
171                                 }
172 #ifdef USE_TLS
173                                 if (u->secure){
174                                         if (u->proto==PROTO_UDP){
175                                                 LOG(L_ERR, "ERROR: do_action: forward: secure uri"
176                                                                 " incompatible with transport %d\n", u->proto);
177                                                 ret=E_BAD_PROTO;
178                                                 goto error_fwd_uri;
179                                         }
180                                         proto=PROTO_TLS;
181                                 }
182 #endif
183                                 /* create a temporary proxy*/
184                                 p=mk_proxy(&u->host, port, proto);
185                                 if (p==0){
186                                         LOG(L_ERR, "ERROR:  bad host name in uri,"
187                                                         " dropping packet\n");
188                                         ret=E_BAD_ADDRESS;
189                                         goto error_fwd_uri;
190                                 }
191                                 ret=forward_request(msg, p, proto);
192                                 /*free_uri(&uri); -- no longer needed, in sip_msg*/
193                                 free_proxy(p); /* frees only p content, not p itself */
194                                 pkg_free(p);
195                                 if (ret>=0) ret=1;
196                         }else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
197                                 ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);
198                                 if (ret>=0) ret=1;
199                         }else{
200                                 LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
201                                                 a->p1_type, a->p2_type);
202                                 ret=E_BUG;
203                         }
204                         break;
205                 case SEND_T:
206                 case SEND_TCP_T:
207                         if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
208                                 LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
209                                                 a->p1_type, a->p2_type);
210                                 ret=E_BUG;
211                                 break;
212                         }
213                         to=(union sockaddr_union*)
214                                         pkg_malloc(sizeof(union sockaddr_union));
215                         if (to==0){
216                                 LOG(L_ERR, "ERROR: do_action: "
217                                                         "memory allocation failure\n");
218                                 ret=E_OUT_OF_MEM;
219                                 break;
220                         }
221                         
222                         p=(struct proxy_l*)a->p1.data;
223                         
224                         if (p->ok==0){
225                                 if (p->host.h_addr_list[p->addr_idx+1])
226                                         p->addr_idx++;
227                                 else 
228                                         p->addr_idx=0;
229                                 p->ok=1;
230                         }
231                         ret=hostent2su( to, &p->host, p->addr_idx,
232                                                 (p->port)?p->port:SIP_PORT );
233                         if (ret==0){
234                                 p->tx++;
235                                 p->tx_bytes+=msg->len;
236                                 if (a->type==SEND_T){
237                                         /*udp*/
238                                         send_sock=get_send_socket(to, PROTO_UDP);
239                                         if (send_sock!=0){
240                                                 ret=udp_send(send_sock, msg->buf, msg->len, to);
241                                         }else{
242                                                 ret=-1;
243                                         }
244                                 }
245 #ifdef USE_TCP
246                                         else{
247                                         /*tcp*/
248                                         ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0);
249                                 }
250 #endif
251                         }
252                         pkg_free(to);
253                         if (ret<0){
254                                 p->errors++;
255                                 p->ok=0;
256                         }else ret=1;
257                         
258                         break;
259                 case LOG_T:
260                         if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
261                                 LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
262                                                 a->p1_type, a->p2_type);
263                                 ret=E_BUG;
264                                 break;
265                         }
266                         LOG(a->p1.number, a->p2.string);
267                         ret=1;
268                         break;
269
270                 /* jku -- introduce a new branch */
271                 case APPEND_BRANCH_T:
272                         if ((a->p1_type!=STRING_ST)) {
273                                 LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
274                                         a->p1_type );
275                                 ret=E_BUG;
276                                 break;
277                         }
278                         ret=append_branch( msg, a->p1.string, 
279                                 a->p1.string ? strlen(a->p1.string):0 );
280                         break;
281
282                 /* jku begin: is_length_greater_than */
283                 case LEN_GT_T:
284                         if (a->p1_type!=NUMBER_ST) {
285                                 LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
286                                         a->p1_type );
287                                 ret=E_BUG;
288                                 break;
289                         }
290                         /* DBG("XXX: message length %d, max %d\n", 
291                                 msg->len, a->p1.number ); */
292                         ret = msg->len >= a->p1.number ? 1 : -1;
293                         break;
294                 /* jku end: is_length_greater_than */
295                         
296                 /* jku - begin : flag processing */
297
298                 case SETFLAG_T:
299                         if (a->p1_type!=NUMBER_ST) {
300                                 LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
301                                         a->p1_type );
302                                 ret=E_BUG;
303                                 break;
304                         }
305                         if (!flag_in_range( a->p1.number )) {
306                                 ret=E_CFG;
307                                 break;
308                         }
309                         setflag( msg, a->p1.number );
310                         ret=1;
311                         break;
312
313                 case RESETFLAG_T:
314                         if (a->p1_type!=NUMBER_ST) {
315                                 LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
316                                         a->p1_type );
317                                 ret=E_BUG;
318                                 break;
319                         }
320                         if (!flag_in_range( a->p1.number )) {
321                                 ret=E_CFG;
322                                 break;
323                         }
324                         resetflag( msg, a->p1.number );
325                         ret=1;
326                         break;
327                         
328                 case ISFLAGSET_T:
329                         if (a->p1_type!=NUMBER_ST) {
330                                 LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
331                                         a->p1_type );
332                                 ret=E_BUG;
333                                 break;
334                         }
335                         if (!flag_in_range( a->p1.number )) {
336                                 ret=E_CFG;
337                                 break;
338                         }
339                         ret=isflagset( msg, a->p1.number );
340                         break;
341                 /* jku - end : flag processing */
342
343                 case ERROR_T:
344                         if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
345                                 LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
346                                                 a->p1_type, a->p2_type);
347                                 ret=E_BUG;
348                                 break;
349                         }
350                         LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
351                                         "not implemented yet\n", a->p1.string, a->p2.string);
352                         ret=1;
353                         break;
354                 case ROUTE_T:
355                         if (a->p1_type!=NUMBER_ST){
356                                 LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
357                                                 a->p1_type);
358                                 ret=E_BUG;
359                                 break;
360                         }
361                         if ((a->p1.number>RT_NO)||(a->p1.number<0)){
362                                 LOG(L_ERR, "ERROR: invalid routing table number in"
363                                                         "route(%lu)\n", a->p1.number);
364                                 ret=E_CFG;
365                                 break;
366                         }
367                         ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
368                         break;
369                 case EXEC_T:
370                         if (a->p1_type!=STRING_ST){
371                                 LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
372                                                 a->p1_type);
373                                 ret=E_BUG;
374                                 break;
375                         }
376                         LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
377                                                 " using dumb version...\n", a->p1.string);
378                         ret=system(a->p1.string);
379                         if (ret!=0){
380                                 LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
381                         }
382                         ret=1;
383                         break;
384                 case REVERT_URI_T:
385                         if (msg->new_uri.s) {
386                                 pkg_free(msg->new_uri.s);
387                                 msg->new_uri.len=0;
388                                 msg->new_uri.s=0;
389                                 msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
390                         };
391                         ret=1;
392                         break;
393                 case SET_HOST_T:
394                 case SET_HOSTPORT_T:
395                 case SET_USER_T:
396                 case SET_USERPASS_T:
397                 case SET_PORT_T:
398                 case SET_URI_T:
399                 case PREFIX_T:
400                 case STRIP_T:
401                 case STRIP_TAIL_T:
402                                 user=0;
403                                 if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
404                                         if (a->p1_type!=NUMBER_ST) {
405                                                 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
406                                                         a->p1_type);
407                                                 break;
408                                         }
409                                 } else if (a->p1_type!=STRING_ST){
410                                         LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
411                                                         a->p1_type);
412                                         ret=E_BUG;
413                                         break;
414                                 }
415                                 if (a->type==SET_URI_T){
416                                         if (msg->new_uri.s) {
417                                                         pkg_free(msg->new_uri.s);
418                                                         msg->new_uri.len=0;
419                                         }
420                                         msg->parsed_uri_ok=0;
421                                         len=strlen(a->p1.string);
422                                         msg->new_uri.s=pkg_malloc(len+1);
423                                         if (msg->new_uri.s==0){
424                                                 LOG(L_ERR, "ERROR: do_action: memory allocation"
425                                                                 " failure\n");
426                                                 ret=E_OUT_OF_MEM;
427                                                 break;
428                                         }
429                                         memcpy(msg->new_uri.s, a->p1.string, len);
430                                         msg->new_uri.s[len]=0;
431                                         msg->new_uri.len=len;
432                                         
433                                         ret=1;
434                                         break;
435                                 }
436                                 if (msg->new_uri.s) {
437                                         tmp=msg->new_uri.s;
438                                         len=msg->new_uri.len;
439                                 }else{
440                                         tmp=msg->first_line.u.request.uri.s;
441                                         len=msg->first_line.u.request.uri.len;
442                                 }
443                                 if (parse_uri(tmp, len, &uri)<0){
444                                         LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
445                                                                 " packet\n", tmp);
446                                         ret=E_UNSPEC;
447                                         break;
448                                 }
449                                 
450                                 new_uri=pkg_malloc(MAX_URI_SIZE);
451                                 if (new_uri==0){
452                                         LOG(L_ERR, "ERROR: do_action: memory allocation "
453                                                                 " failure\n");
454                                         ret=E_OUT_OF_MEM;
455                                         break;
456                                 }
457                                 end=new_uri+MAX_URI_SIZE;
458                                 crt=new_uri;
459                                 /* begin copying */
460                                 len=strlen("sip:"); if(crt+len>end) goto error_uri;
461                                 memcpy(crt,"sip:",len);crt+=len;
462
463                                 /* user */
464
465                                 /* prefix (-jiri) */
466                                 if (a->type==PREFIX_T) {
467                                         tmp=a->p1.string;
468                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
469                                         memcpy(crt,tmp,len);crt+=len;
470                                         /* whatever we had before, with prefix we have username 
471                                            now */
472                                         user=1;
473                                 }
474
475                                 if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
476                                         tmp=a->p1.string;
477                                         len=strlen(tmp);
478                                 } else if (a->type==STRIP_T) {
479                                         if (a->p1.number>uri.user.len) {
480                                                 LOG(L_WARN, "Error: too long strip asked; "
481                                                                         " deleting username: %lu of <%.*s>\n",
482                                                                         a->p1.number, uri.user.len, uri.user.s );
483                                                 len=0;
484                                         } else if (a->p1.number==uri.user.len) {
485                                                 len=0;
486                                         } else {
487                                                 tmp=uri.user.s + a->p1.number;
488                                                 len=uri.user.len - a->p1.number;
489                                         }
490                                 } else if (a->type==STRIP_TAIL_T) {
491                                         if (a->p1.number>uri.user.len) {
492                                                 LOG(L_WARN, "WARNING: too long strip_tail asked; "
493                                                                         " deleting username: %lu of <%.*s>\n",
494                                                                         a->p1.number, uri.user.len, uri.user.s );
495                                                 len=0;
496                                         } else if (a->p1.number==uri.user.len) {
497                                                 len=0;
498                                         } else {
499                                                 tmp=uri.user.s;
500                                                 len=uri.user.len - a->p1.number;
501                                         }
502                                 } else {
503                                         tmp=uri.user.s;
504                                         len=uri.user.len;
505                                 }
506
507                                 if (len){
508                                         if(crt+len>end) goto error_uri;
509                                         memcpy(crt,tmp,len);crt+=len;
510                                         user=1; /* we have an user field so mark it */
511                                 }
512
513                                 if (a->type==SET_USERPASS_T) tmp=0;
514                                 else tmp=uri.passwd.s;
515                                 /* passwd */
516                                 if (tmp){
517                                         len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
518                                         *crt=':'; crt++;
519                                         memcpy(crt,tmp,len);crt+=len;
520                                 }
521                                 /* host */
522                                 if (user || tmp){ /* add @ */
523                                         if(crt+1>end) goto error_uri;
524                                         *crt='@'; crt++;
525                                 }
526                                 if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
527                                         tmp=a->p1.string;
528                                         if (tmp) len = strlen(tmp);
529                                         else len=0;
530                                 } else {
531                                         tmp=uri.host.s;
532                                         len = uri.host.len;
533                                 }
534                                 if (tmp){
535                                         if(crt+len>end) goto error_uri;
536                                         memcpy(crt,tmp,len);crt+=len;
537                                 }
538                                 /* port */
539                                 if (a->type==SET_HOSTPORT_T) tmp=0;
540                                 else if (a->type==SET_PORT_T) {
541                                         tmp=a->p1.string;
542                                         if (tmp) len = strlen(tmp);
543                                         else len = 0;
544                                 } else {
545                                         tmp=uri.port.s;
546                                         len = uri.port.len;
547                                 }
548                                 if (tmp){
549                                         if(crt+len+1>end) goto error_uri;
550                                         *crt=':'; crt++;
551                                         memcpy(crt,tmp,len);crt+=len;
552                                 }
553                                 /* params */
554                                 tmp=uri.params.s;
555                                 if (tmp){
556                                         len=uri.params.len; if(crt+len+1>end) goto error_uri;
557                                         *crt=';'; crt++;
558                                         memcpy(crt,tmp,len);crt+=len;
559                                 }
560                                 /* headers */
561                                 tmp=uri.headers.s;
562                                 if (tmp){
563                                         len=uri.headers.len; if(crt+len+1>end) goto error_uri;
564                                         *crt='?'; crt++;
565                                         memcpy(crt,tmp,len);crt+=len;
566                                 }
567                                 *crt=0; /* null terminate the thing */
568                                 /* copy it to the msg */
569                                 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
570                                 msg->new_uri.s=new_uri;
571                                 msg->new_uri.len=crt-new_uri;
572                                 msg->parsed_uri_ok=0;
573                                 ret=1;
574                                 break;
575                 case IF_T:
576                                 /* if null expr => ignore if? */
577                                 if ((a->p1_type==EXPR_ST)&&a->p1.data){
578                                         v=eval_expr((struct expr*)a->p1.data, msg);
579                                         if (v<0){
580                                                 if (v==EXPR_DROP){ /* hack to quit on DROP*/
581                                                         ret=0;
582                                                         break;
583                                                 }else{
584                                                         LOG(L_WARN,"WARNING: do_action:"
585                                                                                 "error in expression\n");
586                                                 }
587                                         }
588                                         
589                                         ret=1;  /*default is continue */
590                                         if (v>0) {
591                                                 if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
592                                                         ret=run_actions((struct action*)a->p2.data, msg);
593                                                 }
594                                         }else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
595                                                         ret=run_actions((struct action*)a->p3.data, msg);
596                                         }
597                                 }
598                         break;
599                 case MODULE_T:
600                         if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
601                                         ((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
602                                 ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
603                                                                                                           (char*)a->p3.data);
604                         }else{
605                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
606                         }
607                         break;
608                 case FORCE_RPORT_T:
609                         msg->msg_flags|=FL_FORCE_RPORT;
610                         ret=1; /* continue processing */
611                         break;
612                 case SET_ADV_ADDR_T:
613                         if (a->p1_type!=STR_ST){
614                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
615                                                 "type %d\n", a->p1_type);
616                                 ret=E_BUG;
617                                 break;
618                         }
619                         msg->set_global_address=*((str*)a->p1.data);
620                         ret=1; /* continue processing */
621                         break;
622                 case SET_ADV_PORT_T:
623                         if (a->p1_type!=STR_ST){
624                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
625                                                 "type %d\n", a->p1_type);
626                                 ret=E_BUG;
627                                 break;
628                         }
629                         msg->set_global_port=*((str*)a->p1.data);
630                         ret=1; /* continue processing */
631                         break;
632                 default:
633                         LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
634         }
635 /*skip:*/
636         return ret;
637         
638 error_uri:
639         LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
640         if (new_uri) pkg_free(new_uri);
641         return E_UNSPEC;
642 error_fwd_uri:
643         /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
644         return ret;
645 }
646
647
648
649 /* returns: 0, or 1 on success, <0 on error */
650 /* (0 if drop or break encountered, 1 if not ) */
651 int run_actions(struct action* a, struct sip_msg* msg)
652 {
653         struct action* t;
654         int ret=E_UNSPEC;
655         static int rec_lev=0;
656         struct sr_module *mod;
657
658         rec_lev++;
659         if (rec_lev>ROUTE_MAX_REC_LEV){
660                 LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
661                                         " giving up!\n", rec_lev);
662                 ret=E_UNSPEC;
663                 goto error;
664         }
665                 
666         if (a==0){
667                 LOG(L_ERR, "WARNING: run_actions: null action list (rec_level=%d)\n", 
668                         rec_lev);
669                 ret=0;
670         }
671
672         for (t=a; t!=0; t=t->next){
673                 ret=do_action(t, msg);
674                 if(ret==0) break;
675                 /* ignore errors */
676                 /*else if (ret<0){ ret=-1; goto error; }*/
677         }
678         
679         rec_lev--;
680         /* process module onbreak handlers if present */
681         if (rec_lev==0 && ret==0) 
682                 for (mod=modules;mod;mod=mod->next) 
683                         if (mod->exports && mod->exports->onbreak_f) {
684                                 mod->exports->onbreak_f( msg );
685                                 DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
686                         }
687         return ret;
688         
689
690 error:
691         rec_lev--;
692         return ret;
693 }
694
695
696