Merge commit 'origin/ser_core_cvs'
[sip-router] / action.c
1
2 /*
3  * $Id$
4  *
5  * Copyright (C) 2001-2003 FhG Fokus
6  *
7  * This file is part of ser, a free SIP server.
8  *
9  * ser is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * For a license to use the ser software under conditions
15  * other than those described here, or to purchase support for this
16  * software, please contact iptel.org by e-mail at the following addresses:
17  *    info@iptel.org
18  *
19  * ser is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28  * History:
29  * ---------
30  *  2003-02-28  scratchpad compatibility abandoned (jiri)
31  *  2003-01-29  removed scratchpad (jiri)
32  *  2003-03-19  fixed set* len calculation bug & simplified a little the code
33  *              (should be a little faster now) (andrei)
34  *              replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
35  *  2003-04-01  Added support for loose routing in forward (janakj)
36  *  2003-04-12  FORCE_RPORT_T added (andrei)
37  *  2003-04-22  strip_tail added (jiri)
38  *  2003-10-02  added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
39  *  2003-10-29  added FORCE_TCP_ALIAS_T (andrei)
40  *  2004-11-30  added FORCE_SEND_SOCKET_T (andrei)
41  *  2005-12-12  return & drop/exit differentiation (andrei)
42  *  2005-12-19  select framework (mma)
43  *  2006-04-12  updated *_send() calls to use a struct dest_info (andrei)
44  *  2006-07-27  dns cache and dns based send address failover support (andrei)
45  *  2006-12-06  on popular request last_retcode set also by module functions
46  *              (andrei)
47  *  2007-06-14  run_actions & do_action need a ctx or handle now, no more
48  *               static vars (andrei)
49  *  2008-11-18  support for variable parameter module functions (andrei)
50  *  2008-12-03  use lvalues/rvalues for assignments (andrei)
51  *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
52  */
53
54
55 #include "comp_defs.h"
56
57 #include "action.h"
58 #include "config.h"
59 #include "error.h"
60 #include "dprint.h"
61 #include "proxy.h"
62 #include "forward.h"
63 #include "udp_server.h"
64 #include "route.h"
65 #include "parser/msg_parser.h"
66 #include "parser/parse_uri.h"
67 #include "ut.h"
68 #include "lvalue.h"
69 #include "sr_module.h"
70 #include "mem/mem.h"
71 #include "globals.h"
72 #include "dset.h"
73 #include "onsend.h"
74 #include "resolve.h"
75 #ifdef USE_TCP
76 #include "tcp_server.h"
77 #endif
78 #ifdef USE_SCTP
79 #include "sctp_server.h"
80 #endif
81 #include "switch.h"
82
83 #include <sys/types.h>
84 #include <sys/socket.h>
85 #include <netdb.h>
86 #include <stdlib.h>
87 #include <netinet/in.h>
88 #include <arpa/inet.h>
89 #include <string.h>
90
91
92 #ifdef DEBUG_DMALLOC
93 #include <dmalloc.h>
94 #endif
95
96
97 struct onsend_info* p_onsend=0; /* onsend route send info */
98
99 /* ret= 0! if action -> end of list(e.g DROP),
100       > 0 to continue processing next actions
101    and <0 on error */
102 int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
103 {
104         int ret;
105         int v;
106         struct dest_info dst;
107         char* tmp;
108         char *new_uri, *end, *crt;
109         void* f;
110         int len;
111         int user;
112         struct sip_uri uri, next_hop;
113         struct sip_uri *u;
114         unsigned short port;
115         str* dst_host;
116         int i, flags;
117         struct switch_cond_table* sct;
118         struct switch_jmp_table*  sjt;
119         struct rval_expr* rve;
120         struct match_cond_table* mct;
121         struct rvalue* rv;
122         struct rvalue* rv1;
123         struct rval_cache c1;
124         str s;
125         int orig_p2t;
126
127         /* reset the value of error to E_UNSPEC so avoid unknowledgable
128            functions to return with error (status<0) and not setting it
129            leaving there previous error; cache the previous value though
130            for functions which want to process it */
131         prev_ser_error=ser_error;
132         ser_error=E_UNSPEC;
133
134         ret=E_BUG;
135         switch ((unsigned char)a->type){
136                 case DROP_T:
137                                 if (a->val[0].type==RETCODE_ST)
138                                         ret=h->last_retcode;
139                                 else
140                                         ret=(int) a->val[0].u.number;
141                                 h->run_flags|=(unsigned int)a->val[1].u.number;
142                         break;
143                 case FORWARD_T:
144 #ifdef USE_TCP
145                 case FORWARD_TCP_T:
146 #endif
147 #ifdef USE_TLS
148                 case FORWARD_TLS_T:
149 #endif
150 #ifdef USE_SCTP
151                 case FORWARD_SCTP_T:
152 #endif
153                 case FORWARD_UDP_T:
154                         /* init dst */
155                         init_dest_info(&dst);
156                         if (a->type==FORWARD_UDP_T) dst.proto=PROTO_UDP;
157 #ifdef USE_TCP
158                         else if (a->type==FORWARD_TCP_T) dst.proto= PROTO_TCP;
159 #endif
160 #ifdef USE_TLS
161                         else if (a->type==FORWARD_TLS_T) dst.proto= PROTO_TLS;
162 #endif
163 #ifdef USE_SCTP
164                         else if (a->type==FORWARD_SCTP_T) dst.proto=PROTO_SCTP;
165 #endif
166                         else dst.proto=PROTO_NONE;
167                         if (a->val[0].type==URIHOST_ST){
168                                 /*parse uri*/
169
170                                 if (msg->dst_uri.len) {
171                                         ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
172                                                                         &next_hop);
173                                         u = &next_hop;
174                                 } else {
175                                         ret = parse_sip_msg_uri(msg);
176                                         u = &msg->parsed_uri;
177                                 }
178
179                                 if (ret<0) {
180                                         LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
181                                                                 " dropping packet\n");
182                                         break;
183                                 }
184
185                                 switch (a->val[1].type){
186                                         case URIPORT_ST:
187                                                                         port=u->port_no;
188                                                                         break;
189                                         case NUMBER_ST:
190                                                                         port=a->val[1].u.number;
191                                                                         break;
192                                         default:
193                                                         LOG(L_CRIT, "BUG: do_action bad forward 2nd"
194                                                                                 " param type (%d)\n", a->val[1].type);
195                                                         ret=E_UNSPEC;
196                                                         goto error_fwd_uri;
197                                 }
198                                 if (dst.proto == PROTO_NONE){ /* only if proto not set get it
199                                                                                          from the uri */
200                                         switch(u->proto){
201                                                 case PROTO_NONE:
202                                                         /*dst.proto=PROTO_UDP; */
203                                                         /* no proto, try to get it from the dns */
204                                                         break;
205                                                 case PROTO_UDP:
206 #ifdef USE_TCP
207                                                 case PROTO_TCP:
208 #endif
209 #ifdef USE_TLS
210                                                 case PROTO_TLS:
211 #endif
212 #ifdef USE_SCTP
213                                                 case PROTO_SCTP:
214 #endif
215                                                         dst.proto=u->proto;
216                                                         break;
217                                                 default:
218                                                         LOG(L_ERR,"ERROR: do action: forward: bad uri"
219                                                                         " transport %d\n", u->proto);
220                                                         ret=E_BAD_PROTO;
221                                                         goto error_fwd_uri;
222                                         }
223 #ifdef USE_TLS
224                                         if (u->type==SIPS_URI_T){
225                                                 if (u->proto==PROTO_UDP){
226                                                         LOG(L_ERR, "ERROR: do_action: forward: secure uri"
227                                                                         " incompatible with transport %d\n",
228                                                                         u->proto);
229                                                         ret=E_BAD_PROTO;
230                                                         goto error_fwd_uri;
231                                                 }
232                                                 dst.proto=PROTO_TLS;
233                                         }
234 #endif
235                                 }
236
237 #ifdef HONOR_MADDR
238                                 if (u->maddr_val.s && u->maddr_val.len)
239                                         dst_host=&u->maddr_val;
240                                 else
241 #endif
242                                         dst_host=&u->host;
243 #ifdef USE_COMP
244                                 dst.comp=u->comp;
245 #endif
246                                 ret=forward_request(msg, dst_host, port, &dst);
247                                 if (ret>=0){
248                                         ret=1;
249                                 }
250                         }else if ((a->val[0].type==PROXY_ST) && (a->val[1].type==NUMBER_ST)){
251                                 if (dst.proto==PROTO_NONE)
252                                         dst.proto=msg->rcv.proto;
253                                 proxy2su(&dst.to,  (struct proxy_l*)a->val[0].u.data);
254                                 ret=forward_request(msg, 0, 0, &dst);
255                                 if (ret>=0){
256                                         ret=1;
257                                         proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
258                                 }else if (ser_error!=E_OK){
259                                         proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
260                                 }
261                         }else{
262                                 LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
263                                                 a->val[0].type, a->val[1].type);
264                                 ret=E_BUG;
265                         }
266                         break;
267                 case SEND_T:
268                 case SEND_TCP_T:
269                         if ((a->val[0].type!= PROXY_ST)|(a->val[1].type!=NUMBER_ST)){
270                                 LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
271                                                 a->val[0].type, a->val[1].type);
272                                 ret=E_BUG;
273                                 break;
274                         }
275                         /* init dst */
276                         init_dest_info(&dst);
277                         ret=proxy2su(&dst.to,  (struct proxy_l*)a->val[0].u.data);
278                         if (ret==0){
279                                 if (p_onsend){
280                                         tmp=p_onsend->buf;
281                                         len=p_onsend->len;
282                                 }else{
283                                         tmp=msg->buf;
284                                         len=msg->len;
285                                 }
286                                 if (a->type==SEND_T){
287                                         /*udp*/
288                                         dst.proto=PROTO_UDP; /* not really needed for udp_send */
289                                         dst.send_sock=get_send_socket(msg, &dst.to, PROTO_UDP);
290                                         if (dst.send_sock!=0){
291                                                 ret=udp_send(&dst, tmp, len);
292                                         }else{
293                                                 ret=-1;
294                                         }
295                                 }
296 #ifdef USE_TCP
297                                         else{
298                                                 /*tcp*/
299                                                 dst.proto=PROTO_TCP;
300                                                 dst.id=0;
301                                                 ret=tcp_send(&dst, 0, tmp, len);
302                                 }
303 #endif
304                         }else{
305                                 ret=E_BUG;
306                                 break;
307                         }
308                         proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
309                         if (ret>=0) ret=1;
310
311                         break;
312                 case LOG_T:
313                         if ((a->val[0].type!=NUMBER_ST)|(a->val[1].type!=STRING_ST)){
314                                 LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
315                                                 a->val[0].type, a->val[1].type);
316                                 ret=E_BUG;
317                                 break;
318                         }
319                         LOG_(DEFAULT_FACILITY, a->val[0].u.number, "<script>: ", "%s", 
320                                  a->val[1].u.string);
321                         ret=1;
322                         break;
323
324                 /* jku -- introduce a new branch */
325                 case APPEND_BRANCH_T:
326                         if ((a->val[0].type!=STRING_ST)) {
327                                 LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
328                                         a->val[0].type );
329                                 ret=E_BUG;
330                                 break;
331                         }
332                         ret=append_branch( msg, a->val[0].u.string,
333                                            a->val[0].u.string ? strlen(a->val[0].u.string):0,
334                                            0, 0, a->val[1].u.number, 0);
335                         break;
336
337                 /* jku begin: is_length_greater_than */
338                 case LEN_GT_T:
339                         if (a->val[0].type!=NUMBER_ST) {
340                                 LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
341                                         a->val[0].type );
342                                 ret=E_BUG;
343                                 break;
344                         }
345                         /* DBG("XXX: message length %d, max %d\n",
346                                 msg->len, a->val[0].u.number ); */
347                         ret = msg->len >= a->val[0].u.number ? 1 : -1;
348                         break;
349                 /* jku end: is_length_greater_than */
350
351                 /* jku - begin : flag processing */
352
353                 case SETFLAG_T:
354                         if (a->val[0].type!=NUMBER_ST) {
355                                 LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
356                                         a->val[0].type );
357                                 ret=E_BUG;
358                                 break;
359                         }
360                         if (!flag_in_range( a->val[0].u.number )) {
361                                 ret=E_CFG;
362                                 break;
363                         }
364                         setflag( msg, a->val[0].u.number );
365                         ret=1;
366                         break;
367
368                 case RESETFLAG_T:
369                         if (a->val[0].type!=NUMBER_ST) {
370                                 LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
371                                         a->val[0].type );
372                                 ret=E_BUG;
373                                 break;
374                         }
375                         if (!flag_in_range( a->val[0].u.number )) {
376                                 ret=E_CFG;
377                                 break;
378                         }
379                         resetflag( msg, a->val[0].u.number );
380                         ret=1;
381                         break;
382
383                 case ISFLAGSET_T:
384                         if (a->val[0].type!=NUMBER_ST) {
385                                 LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
386                                         a->val[0].type );
387                                 ret=E_BUG;
388                                 break;
389                         }
390                         if (!flag_in_range( a->val[0].u.number )) {
391                                 ret=E_CFG;
392                                 break;
393                         }
394                         ret=isflagset( msg, a->val[0].u.number );
395                         break;
396                 /* jku - end : flag processing */
397
398                 case AVPFLAG_OPER_T:  {
399                         struct search_state st;
400                         avp_t* avp;
401                         int flag;
402                         ret = 0;
403                         flag = a->val[1].u.number;
404                         if ((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL || (a->val[0].u.attr->type & AVP_NAME_RE)!=0) {
405                                 for (avp=search_first_avp(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, &st); avp; avp = search_next_avp(&st, NULL)) {
406                                         switch (a->val[2].u.number) {   /* oper: 0..reset, 1..set, -1..no change */
407                                                 case 0:
408                                                         avp->flags &= ~(avp_flags_t)a->val[1].u.number;
409                                                         break;
410                                                 case 1:
411                                                         avp->flags |= (avp_flags_t)a->val[1].u.number;
412                                                         break;
413                                                 default:;
414                                         }
415                                         ret = ret || ((avp->flags & (avp_flags_t)a->val[1].u.number) != 0);
416                                 }
417                         }
418                         else {
419                                 avp = search_avp_by_index(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, a->val[0].u.attr->index);
420                                 if (avp) {
421                                         switch (a->val[2].u.number) {   /* oper: 0..reset, 1..set, -1..no change */
422                                                 case 0:
423                                                         avp->flags &= ~(avp_flags_t)a->val[1].u.number;
424                                                         break;
425                                                 case 1:
426                                                         avp->flags |= (avp_flags_t)a->val[1].u.number;
427                                                         break;
428                                                 default:;
429                                         }
430                                         ret = (avp->flags & (avp_flags_t)a->val[1].u.number) != 0;
431                                 }
432                         }
433                         if (ret==0)
434                                 ret = -1;
435                         break;
436                 }
437                 case ERROR_T:
438                         if ((a->val[0].type!=STRING_ST)|(a->val[1].type!=STRING_ST)){
439                                 LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
440                                                 a->val[0].type, a->val[1].type);
441                                 ret=E_BUG;
442                                 break;
443                         }
444                         LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
445                                         "not implemented yet\n", a->val[0].u.string, a->val[1].u.string);
446                         ret=1;
447                         break;
448                 case ROUTE_T:
449                         if (a->val[0].type!=NUMBER_ST){
450                                 LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
451                                                 a->val[0].type);
452                                 ret=E_BUG;
453                                 break;
454                         }
455                         if ((a->val[0].u.number>=main_rt.idx)||(a->val[0].u.number<0)){
456                                 LOG(L_ERR, "ERROR: invalid routing table number in"
457                                                         "route(%lu)\n", a->val[0].u.number);
458                                 ret=E_CFG;
459                                 break;
460                         }
461                         /*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
462                         ret=run_actions(h, main_rt.rlist[a->val[0].u.number], msg);
463                         h->last_retcode=ret;
464                         h->run_flags&=~(RETURN_R_F|BREAK_R_F); /* absorb return & break */
465                         break;
466                 case EXEC_T:
467                         if (a->val[0].type!=STRING_ST){
468                                 LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
469                                                 a->val[0].type);
470                                 ret=E_BUG;
471                                 break;
472                         }
473                         LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
474                                                 " using dumb version...\n", a->val[0].u.string);
475                         ret=system(a->val[0].u.string);
476                         if (ret!=0){
477                                 LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
478                         }
479                         ret=1;
480                         break;
481                 case REVERT_URI_T:
482                         if (msg->new_uri.s) {
483                                 pkg_free(msg->new_uri.s);
484                                 msg->new_uri.len=0;
485                                 msg->new_uri.s=0;
486                                 msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
487                         };
488                         ret=1;
489                         break;
490                 case SET_HOST_T:
491                 case SET_HOSTPORT_T:
492                 case SET_HOSTPORTTRANS_T:
493                 case SET_HOSTALL_T:
494                 case SET_USER_T:
495                 case SET_USERPASS_T:
496                 case SET_PORT_T:
497                 case SET_URI_T:
498                 case PREFIX_T:
499                 case STRIP_T:
500                 case STRIP_TAIL_T:
501                 case SET_USERPHONE_T:
502                                 user=0;
503                                 if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
504                                         if (a->val[0].type!=NUMBER_ST) {
505                                                 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
506                                                         a->val[0].type);
507                                                 ret=E_BUG;
508                                                 break;
509                                         }
510                                 } else if (a->type!=SET_USERPHONE_T) {
511                                         if (a->val[0].type!=STRING_ST) {
512                                                 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
513                                                         a->val[0].type);
514                                                 ret=E_BUG;
515                                                 break;
516                                         }
517                                 }
518                                 if (a->type==SET_URI_T){
519                                         if (msg->new_uri.s) {
520                                                         pkg_free(msg->new_uri.s);
521                                                         msg->new_uri.len=0;
522                                         }
523                                         msg->parsed_uri_ok=0;
524                                         len=strlen(a->val[0].u.string);
525                                         msg->new_uri.s=pkg_malloc(len+1);
526                                         if (msg->new_uri.s==0){
527                                                 LOG(L_ERR, "ERROR: do_action: memory allocation"
528                                                                 " failure\n");
529                                                 ret=E_OUT_OF_MEM;
530                                                 break;
531                                         }
532                                         memcpy(msg->new_uri.s, a->val[0].u.string, len);
533                                         msg->new_uri.s[len]=0;
534                                         msg->new_uri.len=len;
535
536                                         ret=1;
537                                         break;
538                                 }
539                                 if ((msg->parsed_uri_ok==0) || ((uri.flags & URI_SIP_USER_PHONE)!=0)) {
540                                         if (msg->new_uri.s) {
541                                                 tmp=msg->new_uri.s;
542                                                 len=msg->new_uri.len;
543                                         }else{
544                                                 tmp=msg->first_line.u.request.uri.s;
545                                                 len=msg->first_line.u.request.uri.len;
546                                         }
547                                         /* don't convert sip:user=phone to tel, otherwise we loose parameters */
548                                         orig_p2t=phone2tel;
549                                         phone2tel=0;
550                                         msg->parsed_uri_ok=0;
551                                         if (parse_uri(tmp, len, &uri)<0){
552                                                 phone2tel=orig_p2t;
553                                                 LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
554                                                                         " packet\n", tmp);
555                                                 ret=E_UNSPEC;
556                                                 break;
557                                         }
558                                         phone2tel=orig_p2t;
559                                 } else {
560                                         uri=msg->parsed_uri;
561                                 }
562
563                                 /* skip SET_USERPHONE_T action if the URI is already
564                                  * a tel: or tels: URI, or contains the user=phone param */
565                                 if ((a->type==SET_USERPHONE_T) 
566                                         && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)
567                                                 || ((uri.user_param_val.len==5) && (memcmp(uri.user_param_val.s, "phone", 5)==0)))
568                                 ) {
569                                         ret=1;
570                                         break;
571                                 }
572                                 /* SET_PORT_T does not work with tel: URIs */
573                                 if ((a->type==SET_PORT_T)
574                                         && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
575                                         && ((uri.flags & URI_SIP_USER_PHONE)==0)
576                                 ) {
577                                         LOG(L_ERR, "ERROR: do_action: port number of a tel: URI cannot be set\n");
578                                         ret=E_UNSPEC;
579                                         break;
580                                 }
581
582                                 new_uri=pkg_malloc(MAX_URI_SIZE);
583                                 if (new_uri==0){
584                                         LOG(L_ERR, "ERROR: do_action: memory allocation "
585                                                                 " failure\n");
586                                         ret=E_OUT_OF_MEM;
587                                         break;
588                                 }
589                                 end=new_uri+MAX_URI_SIZE;
590                                 crt=new_uri;
591                                 /* begin copying */
592                                 /* Preserve the URI scheme unless the host part needs
593                                  * to be rewritten, and the shceme is tel: or tels: */
594                                 switch (uri.type) {
595                                 case SIP_URI_T:
596                                         len=s_sip.len;
597                                         tmp=s_sip.s;
598                                         break;
599
600                                 case SIPS_URI_T:
601                                         len=s_sips.len;
602                                         tmp=s_sips.s;
603                                         break;
604
605                                 case TEL_URI_T:
606                                         if ((uri.flags & URI_SIP_USER_PHONE)
607                                                 || (a->type==SET_HOST_T)
608                                                 || (a->type==SET_HOSTPORT_T)
609                                                 || (a->type==SET_HOSTPORTTRANS_T)
610                                         ) {
611                                                 len=s_sip.len;
612                                                 tmp=s_sip.s;
613                                                 break;
614                                         }
615                                         len=s_tel.len;
616                                         tmp=s_tel.s;
617                                         break;
618
619                                 case TELS_URI_T:
620                                         if ((uri.flags & URI_SIP_USER_PHONE)
621                                                 || (a->type==SET_HOST_T)
622                                                 || (a->type==SET_HOSTPORT_T)
623                                                 || (a->type==SET_HOSTPORTTRANS_T)
624                                         ) {
625                                                 len=s_sips.len;
626                                                 tmp=s_sips.s;
627                                                 break;
628                                         }
629                                         len=s_tels.len;
630                                         tmp=s_tels.s;
631                                         break;
632
633                                 default:
634                                         LOG(L_ERR, "ERROR: Unsupported URI scheme (%d), "
635                                                 "reverted to sip:\n",
636                                                 uri.type);
637                                         len=s_sip.len;
638                                         tmp=s_sip.s;
639                                 }
640                                 if(crt+len+1 /* colon */ >end) goto error_uri;
641                                 memcpy(crt,tmp,len);crt+=len;
642                                 *crt=':'; crt++;
643
644                                 /* user */
645
646                                 /* prefix (-jiri) */
647                                 if (a->type==PREFIX_T) {
648                                         tmp=a->val[0].u.string;
649                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
650                                         memcpy(crt,tmp,len);crt+=len;
651                                         /* whatever we had before, with prefix we have username
652                                            now */
653                                         user=1;
654                                 }
655
656                                 if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
657                                         tmp=a->val[0].u.string;
658                                         len=strlen(tmp);
659                                 } else if (a->type==STRIP_T) {
660                                         if (a->val[0].u.number>uri.user.len) {
661                                                 LOG(L_WARN, "Error: too long strip asked; "
662                                                                         " deleting username: %lu of <%.*s>\n",
663                                                                         a->val[0].u.number, uri.user.len, uri.user.s );
664                                                 len=0;
665                                         } else if (a->val[0].u.number==uri.user.len) {
666                                                 len=0;
667                                         } else {
668                                                 tmp=uri.user.s + a->val[0].u.number;
669                                                 len=uri.user.len - a->val[0].u.number;
670                                         }
671                                 } else if (a->type==STRIP_TAIL_T) {
672                                         if (a->val[0].u.number>uri.user.len) {
673                                                 LOG(L_WARN, "WARNING: too long strip_tail asked; "
674                                                                         " deleting username: %lu of <%.*s>\n",
675                                                                         a->val[0].u.number, uri.user.len, uri.user.s );
676                                                 len=0;
677                                         } else if (a->val[0].u.number==uri.user.len) {
678                                                 len=0;
679                                         } else {
680                                                 tmp=uri.user.s;
681                                                 len=uri.user.len - a->val[0].u.number;
682                                         }
683                                 } else {
684                                         tmp=uri.user.s;
685                                         len=uri.user.len;
686                                 }
687
688                                 if (len){
689                                         if(crt+len>end) goto error_uri;
690                                         memcpy(crt,tmp,len);crt+=len;
691                                         user=1; /* we have an user field so mark it */
692                                 }
693
694                                 if (a->type==SET_USERPASS_T) tmp=0;
695                                 else tmp=uri.passwd.s;
696                                 /* passwd */
697                                 if (tmp){
698                                         len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
699                                         *crt=':'; crt++;
700                                         memcpy(crt,tmp,len);crt+=len;
701                                 }
702                                 /* host */
703                                 if ((a->type==SET_HOST_T)
704                                                 || (a->type==SET_HOSTPORT_T)
705                                                 || (a->type==SET_HOSTALL_T)
706                                                 || (a->type==SET_HOSTPORTTRANS_T)
707                                 ) {
708                                         tmp=a->val[0].u.string;
709                                         if (tmp) len = strlen(tmp);
710                                         else len=0;
711                                 } else if ((uri.type==SIP_URI_T)
712                                         || (uri.type==SIPS_URI_T)
713                                         || (uri.flags & URI_SIP_USER_PHONE)
714                                 ) {
715                                         tmp=uri.host.s;
716                                         len=uri.host.len;
717                                 } else {
718                                         tmp=0;
719                                 }
720                                 if (tmp){
721                                         if (user) { /* add @ */
722                                                 if(crt+1>end) goto error_uri;
723                                                 *crt='@'; crt++;
724                                         }
725                                         if(crt+len>end) goto error_uri;
726                                         memcpy(crt,tmp,len);crt+=len;
727                                 }
728                                 if(a->type==SET_HOSTALL_T)
729                                         goto done_seturi;
730                                 /* port */
731                                 if ((a->type==SET_HOSTPORT_T)
732                                                 || (a->type==SET_HOSTPORTTRANS_T))
733                                         tmp=0;
734                                 else if (a->type==SET_PORT_T) {
735                                         tmp=a->val[0].u.string;
736                                         if (tmp) len = strlen(tmp);
737                                         else len = 0;
738                                 } else {
739                                         tmp=uri.port.s;
740                                         len = uri.port.len;
741                                 }
742                                 if (tmp){
743                                         if(crt+len+1>end) goto error_uri;
744                                         *crt=':'; crt++;
745                                         memcpy(crt,tmp,len);crt+=len;
746                                 }
747                                 /* params */
748                                 if ((a->type==SET_HOSTPORTTRANS_T) && uri.transport.s) {
749                                         /* bypass the transport parameter */
750                                         if (uri.params.s < uri.transport.s) {
751                                                 /* there are parameters before transport */
752                                                 len = uri.transport.s - uri.params.s - 1;
753                                                         /* ignore the ';' at the end */
754                                                 if (crt+len+1>end) goto error_uri;
755                                                 *crt=';'; crt++;
756                                                 memcpy(crt,uri.params.s,len);crt+=len;
757                                         }
758                                         len = (uri.params.s + uri.params.len) -
759                                                 (uri.transport.s + uri.transport.len);
760                                         if (len > 0) {
761                                                 /* there are parameters after transport */
762                                                 if (crt+len>end) goto error_uri;
763                                                 tmp = uri.transport.s + uri.transport.len;
764                                                 memcpy(crt,tmp,len);crt+=len;
765                                         }
766                                 } else {
767                                         tmp=uri.params.s;
768                                         if (tmp){
769                                                 len=uri.params.len; if(crt+len+1>end) goto error_uri;
770                                                 *crt=';'; crt++;
771                                                 memcpy(crt,tmp,len);crt+=len;
772                                         }
773                                 }
774                                 /* Add the user=phone param if a tel: or tels:
775                                  * URI was converted to sip: or sips:.
776                                  * (host part of a tel/tels URI was set.)
777                                  * Or in case of sip: URI and SET_USERPHONE_T action */
778                                 if (((((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
779                                         && ((uri.flags & URI_SIP_USER_PHONE)==0))
780                                         && ((a->type==SET_HOST_T)
781                                                 || (a->type==SET_HOSTPORT_T)
782                                                 || (a->type==SET_HOSTPORTTRANS_T)))
783                                         || (a->type==SET_USERPHONE_T)
784                                 ) {
785                                         tmp=";user=phone";
786                                         len=strlen(tmp);
787                                         if(crt+len>end) goto error_uri;
788                                         memcpy(crt,tmp,len);crt+=len;
789                                 }
790                                 /* headers */
791                                 tmp=uri.headers.s;
792                                 if (tmp){
793                                         len=uri.headers.len; if(crt+len+1>end) goto error_uri;
794                                         *crt='?'; crt++;
795                                         memcpy(crt,tmp,len);crt+=len;
796                                 }
797         done_seturi:
798                                 *crt=0; /* null terminate the thing */
799                                 /* copy it to the msg */
800                                 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
801                                 msg->new_uri.s=new_uri;
802                                 msg->new_uri.len=crt-new_uri;
803                                 msg->parsed_uri_ok=0;
804                                 ret=1;
805                                 break;
806                 case IF_T:
807                                 /* if null expr => ignore if? */
808                                 if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
809                                         v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
810 #if 0
811                                         if (v<0){
812                                                 if (v==EXPR_DROP){ /* hack to quit on DROP*/
813                                                         ret=0;
814                                                         break;
815                                                 }else{
816                                                         LOG(L_WARN,"WARNING: do_action:"
817                                                                                 "error in expression\n");
818                                                 }
819                                         }
820 #endif
821                                         if (h->run_flags & EXIT_R_F){
822                                                 ret=0;
823                                                 break;
824                                         }
825                                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
826                                                                                                                             break in expr*/
827                                         ret=1;  /*default is continue */
828                                         if (v>0) {
829                                                 if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
830                                                         ret=run_actions(h,
831                                                                                 (struct action*)a->val[1].u.data, msg);
832                                                 }
833                                         }else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
834                                                         ret=run_actions(h,
835                                                                                 (struct action*)a->val[2].u.data, msg);
836                                         }
837                                 }
838                         break;
839                 case MODULE_T:
840                         if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
841                                         (f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
842                                 ret=((cmd_function)f)(msg,
843                                                                                 (char*)a->val[2].u.data,
844                                                                                 (char*)a->val[3].u.data
845                                                                         );
846                                 if (ret==0) h->run_flags|=EXIT_R_F;
847                                 h->last_retcode=ret;
848                         } else {
849                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
850                         }
851                         break;
852                 /* instead of using the parameter number, we use different names
853                  * for calls to functions with 3, 4, 5, 6 or variable number of
854                  * parameters due to performance reasons */
855                 case MODULE3_T:
856                         if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
857                                         (f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
858                                 ret=((cmd_function3)f)(msg,
859                                                                                 (char*)a->val[2].u.data,
860                                                                                 (char*)a->val[3].u.data,
861                                                                                 (char*)a->val[4].u.data
862                                                                         );
863                                 if (ret==0) h->run_flags|=EXIT_R_F;
864                                 h->last_retcode=ret;
865                         } else {
866                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
867                         }
868                         break;
869                 case MODULE4_T:
870                         if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
871                                         (f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
872                                 ret=((cmd_function4)f)(msg,
873                                                                                 (char*)a->val[2].u.data,
874                                                                                 (char*)a->val[3].u.data,
875                                                                                 (char*)a->val[4].u.data,
876                                                                                 (char*)a->val[5].u.data
877                                                                         );
878                                 if (ret==0) h->run_flags|=EXIT_R_F;
879                                 h->last_retcode=ret;
880                         } else {
881                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
882                         }
883                         break;
884                 case MODULE5_T:
885                         if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
886                                         (f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
887                                 ret=((cmd_function5)f)(msg,
888                                                                                 (char*)a->val[2].u.data,
889                                                                                 (char*)a->val[3].u.data,
890                                                                                 (char*)a->val[4].u.data,
891                                                                                 (char*)a->val[5].u.data,
892                                                                                 (char*)a->val[6].u.data
893                                                                         );
894                                 if (ret==0) h->run_flags|=EXIT_R_F;
895                                 h->last_retcode=ret;
896                         } else {
897                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
898                         }
899                         break;
900                 case MODULE6_T:
901                         if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
902                                         (f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
903                                 ret=((cmd_function6)f)(msg,
904                                                                                 (char*)a->val[2].u.data,
905                                                                                 (char*)a->val[3].u.data,
906                                                                                 (char*)a->val[4].u.data,
907                                                                                 (char*)a->val[5].u.data,
908                                                                                 (char*)a->val[6].u.data,
909                                                                                 (char*)a->val[7].u.data
910                                                                         );
911                                 if (ret==0) h->run_flags|=EXIT_R_F;
912                                 h->last_retcode=ret;
913                         } else {
914                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
915                         }
916                         break;
917                 case MODULEX_T:
918                         if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
919                                         (f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
920                                 ret=((cmd_function_var)f)(msg,
921                                                                                         a->val[1].u.number,
922                                                                                         &a->val[2]
923                                                                                 );
924                                 if (ret==0) h->run_flags|=EXIT_R_F;
925                                 h->last_retcode=ret;
926                         } else {
927                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
928                         }
929                         break;
930                 case EVAL_T:
931                         /* only eval the expression to account for possible
932                            side-effect */
933                         rval_expr_eval_int(h, msg, &v,
934                                         (struct rval_expr*)a->val[0].u.data);
935                         if (h->run_flags & EXIT_R_F){
936                                 ret=0;
937                                 break;
938                         }
939                         h->run_flags &= ~RETURN_R_F|BREAK_R_F; /* catch return & break in
940                                                                                                           expr */
941                         ret=1; /* default is continue */
942                         break;
943                 case SWITCH_COND_T:
944                         sct=(struct switch_cond_table*)a->val[1].u.data;
945                         if (unlikely( rval_expr_eval_int(h, msg, &v,
946                                                                         (struct rval_expr*)a->val[0].u.data) <0)){
947                                 /* handle error in expression => use default */
948                                 ret=-1;
949                                 goto sw_cond_def;
950                         }
951                         if (h->run_flags & EXIT_R_F){
952                                 ret=0;
953                                 break;
954                         }
955                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break
956                                                                                                             in expr */
957                         ret=1; /* default is continue */
958                         for(i=0; i<sct->n; i++)
959                                 if (sct->cond[i]==v){
960                                         if (likely(sct->jump[i])){
961                                                 ret=run_actions(h, sct->jump[i], msg);
962                                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
963                                                                                                            returns passthrough */
964                                         }
965                                         goto skip;
966                                 }
967 sw_cond_def:
968                         if (sct->def){
969                                 ret=run_actions(h, sct->def, msg);
970                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
971                                                                                            returns passthrough */
972                         }
973                         break;
974                 case SWITCH_JT_T:
975                         sjt=(struct switch_jmp_table*)a->val[1].u.data;
976                         if (unlikely( rval_expr_eval_int(h, msg, &v,
977                                                                         (struct rval_expr*)a->val[0].u.data) <0)){
978                                 /* handle error in expression => use default */
979                                 ret=-1;
980                                 goto sw_jt_def;
981                         }
982                         if (h->run_flags & EXIT_R_F){
983                                 ret=0;
984                                 break;
985                         }
986                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break
987                                                                                                             in expr */
988                         ret=1; /* default is continue */
989                         if (likely(v >= sjt->first && v <= sjt->last)){
990                                 if (likely(sjt->tbl[v - sjt->first])){
991                                         ret=run_actions(h, sjt->tbl[v - sjt->first], msg);
992                                         h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
993                                                                                                    returns passthrough */
994                                 }
995                                 break; 
996                         }else{
997                                 for(i=0; i<sjt->rest.n; i++)
998                                         if (sjt->rest.cond[i]==v){
999                                                 if (likely(sjt->rest.jump[i])){
1000                                                         ret=run_actions(h, sjt->rest.jump[i], msg);
1001                                                         h->run_flags &= ~BREAK_R_F; /* catch breaks, but 
1002                                                                                                                    let returns pass */
1003                                                 }
1004                                                 goto skip;
1005                                         }
1006                         }
1007                         /* not found => try default */
1008 sw_jt_def:
1009                         if (sjt->rest.def){
1010                                 ret=run_actions(h, sjt->rest.def, msg);
1011                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1012                                                                                            returns passthrough */
1013                         }
1014                         break;
1015                 case BLOCK_T:
1016                         if (likely(a->val[0].u.data)){
1017                                 ret=run_actions(h, (struct action*)a->val[0].u.data, msg);
1018                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1019                                                                                            returns passthrough */
1020                         }
1021                         break;
1022                 case MATCH_COND_T:
1023                         mct=(struct match_cond_table*)a->val[1].u.data;
1024                         rval_cache_init(&c1);
1025                         rv=0;
1026                         rv1=0;
1027                         ret=rval_expr_eval_rvint(h, msg, &rv, &v, 
1028                                                                         (struct rval_expr*)a->val[0].u.data, &c1);
1029                                                                         
1030                         if (unlikely( ret<0)){
1031                                 /* handle error in expression => use default */
1032                                 ret=-1;
1033                                 goto match_cond_def;
1034                         }
1035                         if (h->run_flags & EXIT_R_F){
1036                                 ret=0;
1037                                 break;
1038                         }
1039                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break
1040                                                                                                             in expr */
1041                         if (likely(rv)){
1042                                 rv1=rval_convert(h, msg, RV_STR, rv, &c1);
1043                                 if (unlikely(rv1==0)){
1044                                         ret=-1;
1045                                         goto match_cond_def;
1046                                 }
1047                                 s=rv1->v.s;
1048                         }else{
1049                                 /* int result in v */
1050                                 rval_cache_clean(&c1);
1051                                 s.s=sint2str(v, &s.len);
1052                         }
1053                         ret=1; /* default is continue */
1054                         for(i=0; i<mct->n; i++)
1055                                 if (( mct->match[i].type==MATCH_STR &&
1056                                                 mct->match[i].l.s.len==s.len &&
1057                                                 memcmp(mct->match[i].l.s.s, s.s, s.len) == 0 ) ||
1058                                          ( mct->match[i].type==MATCH_RE &&
1059                                           regexec(mct->match[i].l.regex, s.s, 0, 0, 0) == 0)
1060                                         ){
1061                                         if (likely(mct->jump[i])){
1062                                                 ret=run_actions(h, mct->jump[i], msg);
1063                                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1064                                                                                                            returns passthrough */
1065                                         }
1066                                         goto match_cleanup;
1067                                 }
1068 match_cond_def:
1069                         if (mct->def){
1070                                 ret=run_actions(h, mct->def, msg);
1071                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1072                                                                                            returns passthrough */
1073                         }
1074 match_cleanup:
1075                         if (rv1){
1076                                 rval_destroy(rv1);
1077                                 rval_destroy(rv);
1078                                 rval_cache_clean(&c1);
1079                         }else if (rv){
1080                                 rval_destroy(rv);
1081                                 rval_cache_clean(&c1);
1082                         }
1083                         break;
1084                 case WHILE_T:
1085                         i=0;
1086                         flags=0;
1087                         rve=(struct rval_expr*)a->val[0].u.data;
1088                         ret=1;
1089                         while(!(flags & BREAK_R_F) && 
1090                                         (rval_expr_eval_int(h, msg, &v, rve) == 0) && v){
1091                                 i++;
1092                                 if (unlikely(i > cfg_get(core, core_cfg, max_while_loops))){
1093                                         LOG(L_ERR, "ERROR: runaway while (%d, %d): more then"
1094                                                                 " %d loops\n", 
1095                                                                 rve->fpos.s_line, rve->fpos.s_col,
1096                                                                 cfg_get(core, core_cfg, max_while_loops));
1097                                         ret=-1;
1098                                         break;
1099                                 }
1100                                 if (likely(a->val[1].u.data)){
1101                                         ret=run_actions(h, (struct action*)a->val[1].u.data, msg);
1102                                         flags|=h->run_flags;
1103                                         h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1104                                                                                                    returns passthrough */
1105                                 }
1106                         }
1107                         break;
1108                 case FORCE_RPORT_T:
1109                         msg->msg_flags|=FL_FORCE_RPORT;
1110                         ret=1; /* continue processing */
1111                         break;
1112                 case UDP_MTU_TRY_PROTO_T:
1113                         msg->msg_flags|= (unsigned int)a->val[0].u.number & FL_MTU_FB_MASK;
1114                         ret=1; /* continue processing */
1115                         break;
1116                 case SET_ADV_ADDR_T:
1117                         if (a->val[0].type!=STR_ST){
1118                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
1119                                                 "type %d\n", a->val[0].type);
1120                                 ret=E_BUG;
1121                                 break;
1122                         }
1123                         msg->set_global_address=*((str*)a->val[0].u.data);
1124                         ret=1; /* continue processing */
1125                         break;
1126                 case SET_ADV_PORT_T:
1127                         if (a->val[0].type!=STR_ST){
1128                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
1129                                                 "type %d\n", a->val[0].type);
1130                                 ret=E_BUG;
1131                                 break;
1132                         }
1133                         msg->set_global_port=*((str*)a->val[0].u.data);
1134                         ret=1; /* continue processing */
1135                         break;
1136 #ifdef USE_TCP
1137                 case FORCE_TCP_ALIAS_T:
1138                         if ( msg->rcv.proto==PROTO_TCP
1139 #ifdef USE_TLS
1140                                         || msg->rcv.proto==PROTO_TLS
1141 #endif
1142                            ){
1143
1144                                 if (a->val[0].type==NOSUBTYPE)  port=msg->via1->port;
1145                                 else if (a->val[0].type==NUMBER_ST) port=(int)a->val[0].u.number;
1146                                 else{
1147                                         LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
1148                                                         " port type %d\n", a->val[0].type);
1149                                         ret=E_BUG;
1150                                         break;
1151                                 }
1152
1153                                 if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
1154                                                                         msg->rcv.proto)!=0){
1155                                         LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
1156                                         ret=E_UNSPEC;
1157                                         break;
1158                                 }
1159                         }
1160 #endif
1161                         ret=1; /* continue processing */
1162                         break;
1163                 case FORCE_SEND_SOCKET_T:
1164                         if (a->val[0].type!=SOCKETINFO_ST){
1165                                 LOG(L_CRIT, "BUG: do_action: bad force_send_socket argument"
1166                                                 " type: %d\n", a->val[0].type);
1167                                 ret=E_BUG;
1168                                 break;
1169                         }
1170                         msg->force_send_socket=(struct socket_info*)a->val[0].u.data;
1171                         ret=1; /* continue processing */
1172                         break;
1173
1174                 case ADD_T:
1175                 case ASSIGN_T:
1176                         v=lval_assign(h, msg, (struct lvalue*)a->val[0].u.data,
1177                                                                   (struct rval_expr*)a->val[1].u.data);
1178                         if (likely(v>=0))
1179                                 ret = 1;
1180                         else if (unlikely (v == EXPR_DROP)) /* hack to quit on DROP*/
1181                                 ret=0;
1182                         else
1183                                 ret=v;
1184                         break;
1185
1186                 default:
1187                         LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
1188         }
1189 skip:
1190         return ret;
1191
1192 error_uri:
1193         LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
1194         if (new_uri) pkg_free(new_uri);
1195         return E_UNSPEC;
1196 error_fwd_uri:
1197         /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
1198         return ret;
1199 }
1200
1201
1202
1203 /* returns: 0, or 1 on success, <0 on error */
1204 /* (0 if drop or break encountered, 1 if not ) */
1205 int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
1206 {
1207         struct action* t;
1208         int ret;
1209         struct sr_module *mod;
1210
1211         ret=E_UNSPEC;
1212         h->rec_lev++;
1213         if (h->rec_lev>ROUTE_MAX_REC_LEV){
1214                 LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
1215                                         " giving up!\n", h->rec_lev);
1216                 ret=E_UNSPEC;
1217                 goto error;
1218         }
1219         if (h->rec_lev==1){
1220                 h->run_flags=0;
1221                 h->last_retcode=0;
1222 #ifdef USE_LONGJMP
1223                 if (setjmp(h->jmp_env)){
1224                         h->rec_lev=0;
1225                         ret=h->last_retcode;
1226                         goto end;
1227                 }
1228 #endif
1229         }
1230
1231         if (a==0){
1232                 DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
1233                                 h->rec_lev);
1234                 ret=1;
1235         }
1236
1237         for (t=a; t!=0; t=t->next){
1238                 ret=do_action(h, t, msg);
1239                 /* break, return or drop/exit stop execution of the current
1240                    block */
1241                 if (h->run_flags & (BREAK_R_F|RETURN_R_F|EXIT_R_F)){
1242                         if (h->run_flags & EXIT_R_F){
1243 #ifdef USE_LONGJMP
1244                                 h->last_retcode=ret;
1245                                 longjmp(h->jmp_env, ret);
1246 #endif
1247                         }
1248                         break;
1249                 }
1250                 /* ignore error returns */
1251         }
1252
1253         h->rec_lev--;
1254 end:
1255         /* process module onbreak handlers if present */
1256         if (h->rec_lev==0 && ret==0)
1257                 for (mod=modules;mod;mod=mod->next)
1258                         if ((mod->mod_interface_ver==0) && mod->exports && 
1259                                         mod->exports->v0.onbreak_f) {
1260                                 mod->exports->v0.onbreak_f( msg );
1261                                 DBG("DEBUG: %s onbreak handler called\n",
1262                                                 mod->exports->c.name);
1263                         }
1264         return ret;
1265
1266
1267 error:
1268         h->rec_lev--;
1269         return ret;
1270 }