New script element, Jan's select function framework (@xxx), extended for
[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  *  2003-10-29  added FORCE_TCP_ALIAS_T (andrei)
39  *  2004-11-30  added FORCE_SEND_SOCKET_T (andrei)
40  *  2005-12-12  return & drop/exit differentiation (andrei)
41  */
42
43
44 #include "comp_defs.h"
45
46 #include "action.h"
47 #include "config.h"
48 #include "error.h"
49 #include "dprint.h"
50 #include "proxy.h"
51 #include "forward.h"
52 #include "udp_server.h"
53 #include "route.h"
54 #include "parser/msg_parser.h"
55 #include "parser/parse_uri.h"
56 #include "ut.h"
57 #include "sr_module.h"
58 #include "mem/mem.h"
59 #include "globals.h"
60 #include "dset.h"
61 #include "onsend.h"
62 #ifdef USE_TCP
63 #include "tcp_server.h"
64 #endif
65
66 #include <sys/types.h>
67 #include <sys/socket.h>
68 #include <netdb.h>
69 #include <stdlib.h>
70 #include <netinet/in.h>
71 #include <arpa/inet.h>
72 #include <string.h>
73
74 #define USE_LONGJMP
75
76 #ifdef USE_LONGJMP
77 #include <setjmp.h>
78 #endif
79
80 #ifdef DEBUG_DMALLOC
81 #include <dmalloc.h>
82 #endif
83
84
85 struct onsend_info* p_onsend=0; /* onsend route send info */
86 static unsigned int run_flags=0;
87 int last_retcode=0; /* last return from a route() */
88
89 /* ret= 0! if action -> end of list(e.g DROP), 
90       > 0 to continue processing next actions
91    and <0 on error */
92 int do_action(struct action* a, struct sip_msg* msg)
93 {
94         int ret;
95         int v;
96         union sockaddr_union* to;
97         struct socket_info* send_sock;
98         struct proxy_l* p;
99         char* tmp;
100         char *new_uri, *end, *crt;
101         int len;
102         int user;
103         struct sip_uri uri, next_hop;
104         struct sip_uri *u;
105         unsigned short port;
106         int proto;
107         unsigned short flags;
108         int_str name, value;
109
110         /* reset the value of error to E_UNSPEC so avoid unknowledgable
111            functions to return with error (status<0) and not setting it
112            leaving there previous error; cache the previous value though
113            for functions which want to process it */
114         prev_ser_error=ser_error;
115         ser_error=E_UNSPEC;
116
117         ret=E_BUG;
118         switch ((unsigned char)a->type){
119                 case DROP_T:
120                                 if (a->p1_type==RETCODE_ST)
121                                         ret=last_retcode;
122                                 else
123                                         ret=(int)a->p1.number;
124                                 run_flags|=(unsigned int)a->p2.number;
125                         break;
126                 case FORWARD_T:
127 #ifdef USE_TCP
128                 case FORWARD_TCP_T:
129 #endif
130 #ifdef USE_TLS
131                 case FORWARD_TLS_T:
132 #endif
133                 case FORWARD_UDP_T:
134
135                         if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;
136 #ifdef USE_TCP
137                         else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;
138 #endif
139 #ifdef USE_TLS
140                         else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
141 #endif
142                         else proto= PROTO_NONE;
143                         if (a->p1_type==URIHOST_ST){
144                                 /*parse uri*/
145
146                                 if (msg->dst_uri.len) {
147                                         ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop);
148                                         u = &next_hop;
149                                 } else {
150                                         ret = parse_sip_msg_uri(msg);
151                                         u = &msg->parsed_uri;
152                                 }
153
154                                 if (ret<0) {
155                                         LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
156                                                                 " dropping packet\n");
157                                         break;
158                                 }
159                                 
160                                 switch (a->p2_type){
161                                         case URIPORT_ST:
162                                                                         port=u->port_no;
163                                                                         break;
164                                         case NUMBER_ST:
165                                                                         port=a->p2.number;
166                                                                         break;
167                                         default:
168                                                         LOG(L_CRIT, "BUG: do_action bad forward 2nd"
169                                                                                 " param type (%d)\n", a->p2_type);
170                                                         ret=E_UNSPEC;
171                                                         goto error_fwd_uri;
172                                 }
173                                 if (proto == PROTO_NONE){ /* only if proto not set get it
174                                                                                          from the uri */
175                                         switch(u->proto){
176                                                 case PROTO_NONE:
177                                                         proto=PROTO_UDP;
178                                                         break;
179                                                 case PROTO_UDP:
180 #ifdef USE_TCP
181                                                 case PROTO_TCP:
182 #endif
183 #ifdef USE_TLS
184                                                 case PROTO_TLS:
185 #endif
186                                                         proto=u->proto;
187                                                         break;
188                                                 default:
189                                                         LOG(L_ERR,"ERROR: do action: forward: bad uri"
190                                                                         " transport %d\n", u->proto);
191                                                         ret=E_BAD_PROTO;
192                                                         goto error_fwd_uri;
193                                         }
194 #ifdef USE_TLS
195                                         if (u->type==SIPS_URI_T){
196                                                 if (u->proto==PROTO_UDP){
197                                                         LOG(L_ERR, "ERROR: do_action: forward: secure uri"
198                                                                         " incompatible with transport %d\n",
199                                                                         u->proto);
200                                                         ret=E_BAD_PROTO;
201                                                         goto error_fwd_uri;
202                                                 }
203                                                 proto=PROTO_TLS;
204                                         }
205 #endif
206                                 }
207                                 /* create a temporary proxy*/
208                                 p=mk_proxy(&u->host, port, proto);
209                                 if (p==0){
210                                         LOG(L_ERR, "ERROR:  bad host name in uri,"
211                                                         " dropping packet\n");
212                                         ret=E_BAD_ADDRESS;
213                                         goto error_fwd_uri;
214                                 }
215                                 ret=forward_request(msg, p, proto);
216                                 /*free_uri(&uri); -- no longer needed, in sip_msg*/
217                                 free_proxy(p); /* frees only p content, not p itself */
218                                 pkg_free(p);
219                                 if (ret>=0) ret=1;
220                         }else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
221                                 if (proto==PROTO_NONE)
222                                         proto=msg->rcv.proto;
223                                 ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);
224                                 if (ret>=0) ret=1;
225                         }else{
226                                 LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
227                                                 a->p1_type, a->p2_type);
228                                 ret=E_BUG;
229                         }
230                         break;
231                 case SEND_T:
232                 case SEND_TCP_T:
233                         if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
234                                 LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
235                                                 a->p1_type, a->p2_type);
236                                 ret=E_BUG;
237                                 break;
238                         }
239                         to=(union sockaddr_union*)
240                                         pkg_malloc(sizeof(union sockaddr_union));
241                         if (to==0){
242                                 LOG(L_ERR, "ERROR: do_action: "
243                                                         "memory allocation failure\n");
244                                 ret=E_OUT_OF_MEM;
245                                 break;
246                         }
247                         
248                         p=(struct proxy_l*)a->p1.data;
249                         
250                         if (p->ok==0){
251                                 if (p->host.h_addr_list[p->addr_idx+1])
252                                         p->addr_idx++;
253                                 else 
254                                         p->addr_idx=0;
255                                 p->ok=1;
256                         }
257                         ret=hostent2su( to, &p->host, p->addr_idx,
258                                                 (p->port)?p->port:SIP_PORT );
259                         if (ret==0){
260                                 if (p_onsend){
261                                         tmp=p_onsend->buf;
262                                         len=p_onsend->len;
263                                 }else{
264                                         tmp=msg->buf;
265                                         len=msg->len;
266                                 }
267                                 p->tx++;
268                                 p->tx_bytes+=len;
269                                 if (a->type==SEND_T){
270                                         /*udp*/
271                                         send_sock=get_send_socket(msg, to, PROTO_UDP);
272                                         if (send_sock!=0){
273                                                 ret=udp_send(send_sock, tmp, len, to);
274                                         }else{
275                                                 ret=-1;
276                                         }
277                                 }
278 #ifdef USE_TCP
279                                         else{
280                                         /*tcp*/
281                                         ret=tcp_send(PROTO_TCP, tmp, len, to, 0);
282                                 }
283 #endif
284                         }
285                         pkg_free(to);
286                         if (ret<0){
287                                 p->errors++;
288                                 p->ok=0;
289                         }else ret=1;
290                         
291                         break;
292                 case LOG_T:
293                         if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
294                                 LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
295                                                 a->p1_type, a->p2_type);
296                                 ret=E_BUG;
297                                 break;
298                         }
299                         LOG(a->p1.number, "%s", a->p2.string);
300                         ret=1;
301                         break;
302
303                 /* jku -- introduce a new branch */
304                 case APPEND_BRANCH_T:
305                         if ((a->p1_type!=STRING_ST)) {
306                                 LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
307                                         a->p1_type );
308                                 ret=E_BUG;
309                                 break;
310                         }
311                         ret=append_branch( msg, a->p1.string, 
312                                            a->p1.string ? strlen(a->p1.string):0,
313                                            0, 0, a->p2.number, 0);
314                         break;
315
316                 /* jku begin: is_length_greater_than */
317                 case LEN_GT_T:
318                         if (a->p1_type!=NUMBER_ST) {
319                                 LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
320                                         a->p1_type );
321                                 ret=E_BUG;
322                                 break;
323                         }
324                         /* DBG("XXX: message length %d, max %d\n", 
325                                 msg->len, a->p1.number ); */
326                         ret = msg->len >= a->p1.number ? 1 : -1;
327                         break;
328                 /* jku end: is_length_greater_than */
329                         
330                 /* jku - begin : flag processing */
331
332                 case SETFLAG_T:
333                         if (a->p1_type!=NUMBER_ST) {
334                                 LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
335                                         a->p1_type );
336                                 ret=E_BUG;
337                                 break;
338                         }
339                         if (!flag_in_range( a->p1.number )) {
340                                 ret=E_CFG;
341                                 break;
342                         }
343                         setflag( msg, a->p1.number );
344                         ret=1;
345                         break;
346
347                 case RESETFLAG_T:
348                         if (a->p1_type!=NUMBER_ST) {
349                                 LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
350                                         a->p1_type );
351                                 ret=E_BUG;
352                                 break;
353                         }
354                         if (!flag_in_range( a->p1.number )) {
355                                 ret=E_CFG;
356                                 break;
357                         }
358                         resetflag( msg, a->p1.number );
359                         ret=1;
360                         break;
361                         
362                 case ISFLAGSET_T:
363                         if (a->p1_type!=NUMBER_ST) {
364                                 LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
365                                         a->p1_type );
366                                 ret=E_BUG;
367                                 break;
368                         }
369                         if (!flag_in_range( a->p1.number )) {
370                                 ret=E_CFG;
371                                 break;
372                         }
373                         ret=isflagset( msg, a->p1.number );
374                         break;
375                 /* jku - end : flag processing */
376
377                 case ERROR_T:
378                         if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
379                                 LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
380                                                 a->p1_type, a->p2_type);
381                                 ret=E_BUG;
382                                 break;
383                         }
384                         LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
385                                         "not implemented yet\n", a->p1.string, a->p2.string);
386                         ret=1;
387                         break;
388                 case ROUTE_T:
389                         if (a->p1_type!=NUMBER_ST){
390                                 LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
391                                                 a->p1_type);
392                                 ret=E_BUG;
393                                 break;
394                         }
395                         if ((a->p1.number>RT_NO)||(a->p1.number<0)){
396                                 LOG(L_ERR, "ERROR: invalid routing table number in"
397                                                         "route(%lu)\n", a->p1.number);
398                                 ret=E_CFG;
399                                 break;
400                         }
401                         /*ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;*/
402                         ret=run_actions(rlist[a->p1.number], msg);
403                         last_retcode=ret;
404                         run_flags&=~RETURN_R_F; /* absorb returns */
405                         break;
406                 case EXEC_T:
407                         if (a->p1_type!=STRING_ST){
408                                 LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
409                                                 a->p1_type);
410                                 ret=E_BUG;
411                                 break;
412                         }
413                         LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
414                                                 " using dumb version...\n", a->p1.string);
415                         ret=system(a->p1.string);
416                         if (ret!=0){
417                                 LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
418                         }
419                         ret=1;
420                         break;
421                 case REVERT_URI_T:
422                         if (msg->new_uri.s) {
423                                 pkg_free(msg->new_uri.s);
424                                 msg->new_uri.len=0;
425                                 msg->new_uri.s=0;
426                                 msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
427                         };
428                         ret=1;
429                         break;
430                 case SET_HOST_T:
431                 case SET_HOSTPORT_T:
432                 case SET_USER_T:
433                 case SET_USERPASS_T:
434                 case SET_PORT_T:
435                 case SET_URI_T:
436                 case PREFIX_T:
437                 case STRIP_T:
438                 case STRIP_TAIL_T:
439                                 user=0;
440                                 if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
441                                         if (a->p1_type!=NUMBER_ST) {
442                                                 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
443                                                         a->p1_type);
444                                                 break;
445                                         }
446                                 } else if (a->p1_type!=STRING_ST){
447                                         LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
448                                                         a->p1_type);
449                                         ret=E_BUG;
450                                         break;
451                                 }
452                                 if (a->type==SET_URI_T){
453                                         if (msg->new_uri.s) {
454                                                         pkg_free(msg->new_uri.s);
455                                                         msg->new_uri.len=0;
456                                         }
457                                         msg->parsed_uri_ok=0;
458                                         len=strlen(a->p1.string);
459                                         msg->new_uri.s=pkg_malloc(len+1);
460                                         if (msg->new_uri.s==0){
461                                                 LOG(L_ERR, "ERROR: do_action: memory allocation"
462                                                                 " failure\n");
463                                                 ret=E_OUT_OF_MEM;
464                                                 break;
465                                         }
466                                         memcpy(msg->new_uri.s, a->p1.string, len);
467                                         msg->new_uri.s[len]=0;
468                                         msg->new_uri.len=len;
469                                         
470                                         ret=1;
471                                         break;
472                                 }
473                                 if (msg->new_uri.s) {
474                                         tmp=msg->new_uri.s;
475                                         len=msg->new_uri.len;
476                                 }else{
477                                         tmp=msg->first_line.u.request.uri.s;
478                                         len=msg->first_line.u.request.uri.len;
479                                 }
480                                 if (parse_uri(tmp, len, &uri)<0){
481                                         LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
482                                                                 " packet\n", tmp);
483                                         ret=E_UNSPEC;
484                                         break;
485                                 }
486                                 
487                                 new_uri=pkg_malloc(MAX_URI_SIZE);
488                                 if (new_uri==0){
489                                         LOG(L_ERR, "ERROR: do_action: memory allocation "
490                                                                 " failure\n");
491                                         ret=E_OUT_OF_MEM;
492                                         break;
493                                 }
494                                 end=new_uri+MAX_URI_SIZE;
495                                 crt=new_uri;
496                                 /* begin copying */
497                                 len=strlen("sip:"); if(crt+len>end) goto error_uri;
498                                 memcpy(crt,"sip:",len);crt+=len;
499
500                                 /* user */
501
502                                 /* prefix (-jiri) */
503                                 if (a->type==PREFIX_T) {
504                                         tmp=a->p1.string;
505                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
506                                         memcpy(crt,tmp,len);crt+=len;
507                                         /* whatever we had before, with prefix we have username 
508                                            now */
509                                         user=1;
510                                 }
511
512                                 if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
513                                         tmp=a->p1.string;
514                                         len=strlen(tmp);
515                                 } else if (a->type==STRIP_T) {
516                                         if (a->p1.number>uri.user.len) {
517                                                 LOG(L_WARN, "Error: too long strip asked; "
518                                                                         " deleting username: %lu of <%.*s>\n",
519                                                                         a->p1.number, uri.user.len, uri.user.s );
520                                                 len=0;
521                                         } else if (a->p1.number==uri.user.len) {
522                                                 len=0;
523                                         } else {
524                                                 tmp=uri.user.s + a->p1.number;
525                                                 len=uri.user.len - a->p1.number;
526                                         }
527                                 } else if (a->type==STRIP_TAIL_T) {
528                                         if (a->p1.number>uri.user.len) {
529                                                 LOG(L_WARN, "WARNING: too long strip_tail asked; "
530                                                                         " deleting username: %lu of <%.*s>\n",
531                                                                         a->p1.number, uri.user.len, uri.user.s );
532                                                 len=0;
533                                         } else if (a->p1.number==uri.user.len) {
534                                                 len=0;
535                                         } else {
536                                                 tmp=uri.user.s;
537                                                 len=uri.user.len - a->p1.number;
538                                         }
539                                 } else {
540                                         tmp=uri.user.s;
541                                         len=uri.user.len;
542                                 }
543
544                                 if (len){
545                                         if(crt+len>end) goto error_uri;
546                                         memcpy(crt,tmp,len);crt+=len;
547                                         user=1; /* we have an user field so mark it */
548                                 }
549
550                                 if (a->type==SET_USERPASS_T) tmp=0;
551                                 else tmp=uri.passwd.s;
552                                 /* passwd */
553                                 if (tmp){
554                                         len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
555                                         *crt=':'; crt++;
556                                         memcpy(crt,tmp,len);crt+=len;
557                                 }
558                                 /* host */
559                                 if (user || tmp){ /* add @ */
560                                         if(crt+1>end) goto error_uri;
561                                         *crt='@'; crt++;
562                                 }
563                                 if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
564                                         tmp=a->p1.string;
565                                         if (tmp) len = strlen(tmp);
566                                         else len=0;
567                                 } else {
568                                         tmp=uri.host.s;
569                                         len = uri.host.len;
570                                 }
571                                 if (tmp){
572                                         if(crt+len>end) goto error_uri;
573                                         memcpy(crt,tmp,len);crt+=len;
574                                 }
575                                 /* port */
576                                 if (a->type==SET_HOSTPORT_T) tmp=0;
577                                 else if (a->type==SET_PORT_T) {
578                                         tmp=a->p1.string;
579                                         if (tmp) len = strlen(tmp);
580                                         else len = 0;
581                                 } else {
582                                         tmp=uri.port.s;
583                                         len = uri.port.len;
584                                 }
585                                 if (tmp){
586                                         if(crt+len+1>end) goto error_uri;
587                                         *crt=':'; crt++;
588                                         memcpy(crt,tmp,len);crt+=len;
589                                 }
590                                 /* params */
591                                 tmp=uri.params.s;
592                                 if (tmp){
593                                         len=uri.params.len; if(crt+len+1>end) goto error_uri;
594                                         *crt=';'; crt++;
595                                         memcpy(crt,tmp,len);crt+=len;
596                                 }
597                                 /* headers */
598                                 tmp=uri.headers.s;
599                                 if (tmp){
600                                         len=uri.headers.len; if(crt+len+1>end) goto error_uri;
601                                         *crt='?'; crt++;
602                                         memcpy(crt,tmp,len);crt+=len;
603                                 }
604                                 *crt=0; /* null terminate the thing */
605                                 /* copy it to the msg */
606                                 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
607                                 msg->new_uri.s=new_uri;
608                                 msg->new_uri.len=crt-new_uri;
609                                 msg->parsed_uri_ok=0;
610                                 ret=1;
611                                 break;
612                 case IF_T:
613                                 /* if null expr => ignore if? */
614                                 if ((a->p1_type==EXPR_ST)&&a->p1.data){
615                                         v=eval_expr((struct expr*)a->p1.data, msg);
616 #if 0
617                                         if (v<0){
618                                                 if (v==EXPR_DROP){ /* hack to quit on DROP*/
619                                                         ret=0;
620                                                         break;
621                                                 }else{
622                                                         LOG(L_WARN,"WARNING: do_action:"
623                                                                                 "error in expression\n");
624                                                 }
625                                         }
626 #endif
627                                         if (run_flags & EXIT_R_F){
628                                                 ret=0;
629                                                 break;
630                                         }
631                                         run_flags &= ~RETURN_R_F; /* catch returns in expr */
632                                         ret=1;  /*default is continue */
633                                         if (v>0) {
634                                                 if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
635                                                         ret=run_actions((struct action*)a->p2.data, msg);
636                                                 }
637                                         }else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
638                                                         ret=run_actions((struct action*)a->p3.data, msg);
639                                         }
640                                 }
641                         break;
642                 case MODULE_T:
643                         if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
644                                         ((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
645                                 ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
646                                                                                                           (char*)a->p3.data);
647                                 if (ret==0) run_flags|=EXIT_R_F;
648                         }else{
649                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
650                         }
651                         break;
652                 case FORCE_RPORT_T:
653                         msg->msg_flags|=FL_FORCE_RPORT;
654                         ret=1; /* continue processing */
655                         break;
656                 case SET_ADV_ADDR_T:
657                         if (a->p1_type!=STR_ST){
658                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
659                                                 "type %d\n", a->p1_type);
660                                 ret=E_BUG;
661                                 break;
662                         }
663                         msg->set_global_address=*((str*)a->p1.data);
664                         ret=1; /* continue processing */
665                         break;
666                 case SET_ADV_PORT_T:
667                         if (a->p1_type!=STR_ST){
668                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
669                                                 "type %d\n", a->p1_type);
670                                 ret=E_BUG;
671                                 break;
672                         }
673                         msg->set_global_port=*((str*)a->p1.data);
674                         ret=1; /* continue processing */
675                         break;
676 #ifdef USE_TCP
677                 case FORCE_TCP_ALIAS_T:
678                         if ( msg->rcv.proto==PROTO_TCP
679 #ifdef USE_TLS
680                                         || msg->rcv.proto==PROTO_TLS
681 #endif
682                            ){
683                                 
684                                 if (a->p1_type==NOSUBTYPE)      port=msg->via1->port;
685                                 else if (a->p1_type==NUMBER_ST) port=(int)a->p1.number;
686                                 else{
687                                         LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
688                                                         " port type %d\n", a->p1_type);
689                                         ret=E_BUG;
690                                         break;
691                                 }
692                                                 
693                                 if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
694                                                                         msg->rcv.proto)!=0){
695                                         LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
696                                         ret=E_UNSPEC;
697                                         break;
698                                 }
699                         }
700 #endif
701                         ret=1; /* continue processing */
702                         break;
703                 case FORCE_SEND_SOCKET_T:
704                         if (a->p1_type!=SOCKETINFO_ST){
705                                 LOG(L_CRIT, "BUG: do_action: bad force_send_socket argument"
706                                                 " type: %d\n", a->p1_type);
707                                 ret=E_BUG;
708                                 break;
709                         }
710                         msg->force_send_socket=(struct socket_info*)a->p1.data;
711                         ret=1; /* continue processing */
712                         break;
713
714                 case ADD_T:
715                 case ASSIGN_T:
716                         if (a->p2_type == STRING_ST) {
717                                 value.s = a->p2.str;
718                                 flags = a->p1.attr->type | AVP_VAL_STR;
719                                 name = a->p1.attr->name;
720                                 ret = 1;
721                         } else if (a->p2_type == NUMBER_ST) {
722                                 value.n = a->p2.number;
723                                 flags = a->p1.attr->type;
724                                 name = a->p1.attr->name;
725                                 ret = 1;
726                         } else if (a->p2_type == ACTION_ST) {
727                                 flags = a->p1.attr->type;
728                                 name = a->p1.attr->name;
729                                 if (a->p2.data) {
730                                         value.n = run_actions((struct action*)a->p2.data, msg);
731                                 } else {
732                                         value.n = -1;
733                                 }
734                                 ret = value.n;
735                         } else if(a->p2_type == EXPR_ST && a->p2.data) {
736                                 v = eval_expr((struct expr*)a->p2.data, msg);
737                                 if (v < 0) {
738                                         if (v == EXPR_DROP){ /* hack to quit on DROP*/
739                                                 ret = 0;
740                                                 break;
741                                         } else {
742                                                 LOG(L_WARN,"WARNING: do_action: error in expression\n");
743                                         }
744                                 }
745                                 
746                                 flags = a->p1.attr->type;
747                                 name = a->p1.attr->name;
748                                 value.n = v;
749                         } else if (a->p2_type == AVP_ST) {
750                                 struct search_state st;
751                                 avp_t* avp; 
752                                 
753                                      /* If the action is assign then remove the old avp value before adding
754                                       * new ones
755                                       */
756                                 if ((unsigned char)a->type == ASSIGN_T) delete_avp(a->p1.attr->type, a->p1.attr->name);
757
758                                 avp = search_first_avp(a->p2.attr->type, a->p2.attr->name, &value, &st);
759                                 while(avp) {
760                                              /* We take only the type of value and name from the source avp
761                                               * and reset class and track flags
762                                               */
763                                         flags = a->p1.attr->type | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
764                                         if (add_avp(flags, name, value) < 0) {
765                                                 LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
766                                                 ret=E_UNSPEC;
767                                                 break;
768                                         }
769                                         avp = search_next_avp(&st, &value);
770                                 }
771                                 ret = 1;
772                                 break;
773                         } else if (a->p2_type == SELECT_ST) {
774                                 int r;
775                                 r = run_select(&value.s, a->p2.select, msg);
776                                 if (r < 0) {
777                                         ret=E_UNSPEC;
778                                         break;
779                                 } else if (r > 0) {
780                                         value.s.s = "";
781                                         value.s.len = 0;
782                                 }
783
784                                 flags = a->p1.attr->type | AVP_VAL_STR;
785                                 name = a->p1.attr->name;
786                                 ret = 1;
787                         } else {
788                                 LOG(L_CRIT, "BUG: do_action: Bad right side of avp assignment\n");
789                                 ret=E_BUG;
790                                 break;
791                         }
792
793                         /* If the action is assign then remove the old avp value
794                          * before adding new ones */
795                         if ((unsigned char)a->type == ASSIGN_T) delete_avp(flags, name);
796                         if (add_avp(flags, name, value) < 0) {
797                                 LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
798                                 ret=E_UNSPEC;
799                                 break;
800                         }
801                         break;
802
803                 default:
804                         LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
805         }
806 /*skip:*/
807         return ret;
808         
809 error_uri:
810         LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
811         if (new_uri) pkg_free(new_uri);
812         return E_UNSPEC;
813 error_fwd_uri:
814         /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
815         return ret;
816 }
817
818
819
820 /* returns: 0, or 1 on success, <0 on error */
821 /* (0 if drop or break encountered, 1 if not ) */
822 int run_actions(struct action* a, struct sip_msg* msg)
823 {
824         struct action* t;
825         int ret=E_UNSPEC;
826         static int rec_lev=0;
827         static jmp_buf jmp_env;
828         struct sr_module *mod;
829
830         rec_lev++;
831         if (rec_lev>ROUTE_MAX_REC_LEV){
832                 LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
833                                         " giving up!\n", rec_lev);
834                 ret=E_UNSPEC;
835                 goto error;
836         }
837         if (rec_lev==1){
838                 run_flags=0;
839                 last_retcode=0;
840                 if (setjmp(jmp_env)){
841                         rec_lev=0;
842                         ret=last_retcode;
843                         goto end;
844                 }
845         }
846                 
847         if (a==0){
848                 LOG(L_ERR, "WARNING: run_actions: null action list (rec_level=%d)\n", 
849                         rec_lev);
850                 ret=0;
851         }
852
853         for (t=a; t!=0; t=t->next){
854                 ret=do_action(t, msg);
855                 if (run_flags & (RETURN_R_F|EXIT_R_F)){
856                         if (run_flags & EXIT_R_F){
857                                 last_retcode=ret;
858                                 longjmp(jmp_env, ret);
859                         }
860                         break;
861                 }
862                 /* ignore error returns */
863         }
864         
865         rec_lev--;
866 end:
867         /* process module onbreak handlers if present */
868         if (rec_lev==0 && ret==0) 
869                 for (mod=modules;mod;mod=mod->next) 
870                         if (mod->exports && mod->exports->onbreak_f) {
871                                 mod->exports->onbreak_f( msg );
872                                 DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
873                         }
874         return ret;
875         
876
877 error:
878         rec_lev--;
879         return ret;
880 }
881
882
883