• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

action.c

Go to the documentation of this file.
00001 
00002 /*
00003  * $Id$
00004  *
00005  * Copyright (C) 2001-2003 FhG Fokus
00006  *
00007  * This file is part of ser, a free SIP server.
00008  *
00009  * ser is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * For a license to use the ser software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact iptel.org by e-mail at the following addresses:
00017  *    info@iptel.org
00018  *
00019  * ser is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00027  *
00028  * History:
00029  * ---------
00030  *  2003-02-28  scratchpad compatibility abandoned (jiri)
00031  *  2003-01-29  removed scratchpad (jiri)
00032  *  2003-03-19  fixed set* len calculation bug & simplified a little the code
00033  *              (should be a little faster now) (andrei)
00034  *              replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00035  *  2003-04-01  Added support for loose routing in forward (janakj)
00036  *  2003-04-12  FORCE_RPORT_T added (andrei)
00037  *  2003-04-22  strip_tail added (jiri)
00038  *  2003-10-02  added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
00039  *  2003-10-29  added FORCE_TCP_ALIAS_T (andrei)
00040  *  2004-11-30  added FORCE_SEND_SOCKET_T (andrei)
00041  *  2005-12-12  return & drop/exit differentiation (andrei)
00042  *  2005-12-19  select framework (mma)
00043  *  2006-04-12  updated *_send() calls to use a struct dest_info (andrei)
00044  *  2006-07-27  dns cache and dns based send address failover support (andrei)
00045  *  2006-12-06  on popular request last_retcode set also by module functions
00046  *              (andrei)
00047  *  2007-06-14  run_actions & do_action need a ctx or handle now, no more
00048  *               static vars (andrei)
00049  *  2008-11-18  support for variable parameter module functions (andrei)
00050  *  2008-12-03  use lvalues/rvalues for assignments (andrei)
00051  *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
00052  *  2009-05-04  switched IF_T to rval_expr (andrei)
00053  *  2009-09-15  added SET_{FWD,RPL}_NO_CONNECT, SET_{FWD,RPL}_CLOSE (andrei)
00054  *  2010-06-01  special hack/support for fparam fixups so that they can handle
00055  *               variable RVEs (andrei)
00056  */
00057 
00067 #include "comp_defs.h"
00068 
00069 #include "action.h"
00070 #include "config.h"
00071 #include "error.h"
00072 #include "dprint.h"
00073 #include "proxy.h"
00074 #include "forward.h"
00075 #include "udp_server.h"
00076 #include "route.h"
00077 #include "parser/msg_parser.h"
00078 #include "parser/parse_uri.h"
00079 #include "ut.h"
00080 #include "lvalue.h"
00081 #include "sr_module.h"
00082 #include "select_buf.h"
00083 #include "mem/mem.h"
00084 #include "globals.h"
00085 #include "dset.h"
00086 #include "onsend.h"
00087 #include "resolve.h"
00088 #ifdef USE_TCP
00089 #include "tcp_server.h"
00090 #endif
00091 #ifdef USE_SCTP
00092 #include "sctp_server.h"
00093 #endif
00094 #include "switch.h"
00095 #include "events.h"
00096 #include "cfg/cfg_struct.h"
00097 
00098 #include <sys/types.h>
00099 #include <sys/socket.h>
00100 #include <netdb.h>
00101 #include <stdlib.h>
00102 #include <netinet/in.h>
00103 #include <arpa/inet.h>
00104 #include <string.h>
00105 
00106 
00107 #ifdef DEBUG_DMALLOC
00108 #include <dmalloc.h>
00109 #endif
00110 
00111 int _last_returned_code  = 0;
00112 struct onsend_info* p_onsend=0; /* onsend route send info */
00113 
00114 
00115 
00116 /* handle the exit code of a module function call.
00117  * (used internally in do_action())
00118  * @param h - script handle (h->last_retcode and h->run_flags will be set).
00119  * @param ret - module function (v0 or v2) retcode
00120  * Side-effects: sets _last_returned_code
00121  */
00122 #define MODF_HANDLE_RETCODE(h, ret) \
00123         do { \
00124                 /* if (unlikely((ret)==0)) (h)->run_flags|=EXIT_R_F; */ \
00125                 (h)->run_flags |= EXIT_R_F & (((ret) != 0) -1); \
00126                 (h)->last_retcode=(ret); \
00127                 _last_returned_code = (h)->last_retcode; \
00128         } while(0)
00129 
00130 
00131 
00132 /* frees parameters converted using MODF_RVE_PARAM_CONVERT() from dst.
00133  * (used internally in do_action())
00134  * Assumes src is unchanged.
00135  * Side-effects: clobbers i (int).
00136  */
00137 #define MODF_RVE_PARAM_FREE(cmd, src, dst) \
00138                 for (i=0; i < (dst)[1].u.number; i++) { \
00139                         if ((src)[i+2].type == RVE_ST && (dst)[i+2].u.data) { \
00140                                 if ((dst)[i+2].type == RVE_FREE_FIXUP_ST) {\
00141                                         /* call free_fixup (which should restore the original
00142                                            string) */ \
00143                                         call_fixup((cmd)->free_fixup, &(dst)[i+2].u.data, i+1); \
00144                                 } else if ((dst)[i+2].type == FPARAM_DYN_ST) {\
00145                                         /* completely frees fparam and restore original string */\
00146                                         fparam_free_restore(&(dst)[i+2].u.data); \
00147                                 } \
00148                                 /* free allocated string */ \
00149                                 pkg_free((dst)[i+2].u.data); \
00150                                 (dst)[i+2].u.data = 0; \
00151                         } \
00152                 }
00153 
00154 
00155 /* fills dst from src, converting RVE_ST params to STRING_ST.
00156  * (used internally in do_action())
00157  * @param src - source action_u_t array, as in the action structure
00158  * @param dst - destination action_u_t array, will be filled from src.
00159  * WARNING: dst must be cleaned when done, use MODULE_RVE_PARAM_FREE()
00160  * Side-effects: clobbers i (int), s (str), rv (rvalue*), might jump to error.
00161  */
00162 #define MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst) \
00163         do { \
00164                 (dst)[1]=(src)[1]; \
00165                 for (i=0; i < (src)[1].u.number; i++) { \
00166                         if ((src)[2+i].type == RVE_ST) { \
00167                                 rv=rval_expr_eval((h), (msg), (src)[i+2].u.data); \
00168                                 if (unlikely(rv == 0 || \
00169                                         rval_get_str((h), (msg), &s, rv, 0) < 0)) { \
00170                                         rval_destroy(rv); \
00171                                         ERR("failed to convert RVE to string\n"); \
00172                                         (dst)[1].u.number = i; \
00173                                         MODF_RVE_PARAM_FREE(cmd, src, dst); \
00174                                         goto error; \
00175                                 } \
00176                                 (dst)[i+2].type = STRING_RVE_ST; \
00177                                 (dst)[i+2].u.string = s.s; \
00178                                 (dst)[i+2].u.str.len = s.len; \
00179                                 rval_destroy(rv); \
00180                                 if ((cmd)->fixup) {\
00181                                         if ((cmd)->free_fixup) {\
00182                                                 if (likely( call_fixup((cmd)->fixup, \
00183                                                                                 &(dst)[i+2].u.data, i+1) >= 0) ) { \
00184                                                         /* success => mark it for calling free fixup */ \
00185                                                         if (likely((dst)[i+2].u.data != s.s)) \
00186                                                                 (dst)[i+2].type = RVE_FREE_FIXUP_ST; \
00187                                                 } else { \
00188                                                         /* error calling fixup => mark conv. parameter \
00189                                                            and return error */ \
00190                                                         (dst)[1].u.number = i; \
00191                                                         ERR("runtime fixup failed for %s param %d\n", \
00192                                                                         (cmd)->name, i+1); \
00193                                                         MODF_RVE_PARAM_FREE(cmd, src, dst); \
00194                                                         goto error; \
00195                                                 } \
00196                                         } else if ((cmd)->fixup_flags & FIXUP_F_FPARAM_RVE) { \
00197                                                 if (likely( call_fixup((cmd)->fixup, \
00198                                                                                 &(dst)[i+2].u.data, i+1) >= 0)) { \
00199                                                         if ((dst)[i+2].u.data != s.s) \
00200                                                                 (dst)[i+2].type = FPARAM_DYN_ST; \
00201                                                 } else { \
00202                                                         /* error calling fixup => mark conv. parameter \
00203                                                            and return error */ \
00204                                                         (dst)[1].u.number = i; \
00205                                                         ERR("runtime fixup failed for %s param %d\n", \
00206                                                                         (cmd)->name, i+1); \
00207                                                         MODF_RVE_PARAM_FREE(cmd, src, dst); \
00208                                                         goto error; \
00209                                                 }\
00210                                         } \
00211                                 } \
00212                         } else \
00213                                 (dst)[i+2]=(src)[i+2]; \
00214                 } \
00215         } while(0)
00216 
00217 
00218 
00219 /* call a module function with normal STRING_ST params.
00220  * (used internally in do_action())
00221  * @param f_type - cmd_function type
00222  * @param h
00223  * @param msg
00224  * @param src - source action_u_t array (e.g. action->val)
00225  * @param params... - variable list of parameters, passed to the module
00226  *               function
00227  * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), cmd,
00228  *               might jump to error.
00229  *
00230  */
00231 #ifdef __SUNPRO_C
00232 #define MODF_CALL(f_type, h, msg, src, ...) \
00233         do { \
00234                 cmd=(src)[0].u.data; \
00235                 ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
00236                 MODF_HANDLE_RETCODE(h, ret); \
00237         } while (0)
00238 #else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
00239 #define MODF_CALL(f_type, h, msg, src, params...) \
00240         do { \
00241                 cmd=(src)[0].u.data; \
00242                 ret=((f_type)cmd->function)((msg), ## params ); \
00243                 MODF_HANDLE_RETCODE(h, ret); \
00244         } while (0)
00245 #endif /* __SUNPRO_C */
00246 
00247 
00248 
00249 /* call a module function with possible RVE params.
00250  * (used internally in do_action())
00251  * @param f_type - cmd_function type
00252  * @param h
00253  * @param msg
00254  * @param src - source action_u_t array (e.g. action->val)
00255  * @param dst - temporary action_u_t array used for conversions. It can be
00256  *              used for the function parameters. It's contents it's not
00257  *              valid after the call.
00258  * @param params... - variable list of parameters, passed to the module
00259  *               function
00260  * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), f, dst,
00261  *               might jump to error.
00262  *
00263  */
00264 #ifdef __SUNPRO_C
00265 #define MODF_RVE_CALL(f_type, h, msg, src, dst, ...) \
00266         do { \
00267                 cmd=(src)[0].u.data; \
00268                 MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
00269                 ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
00270                 MODF_HANDLE_RETCODE(h, ret); \
00271                 /* free strings allocated by us or fixups */ \
00272                 MODF_RVE_PARAM_FREE(cmd, src, dst); \
00273         } while (0)
00274 #else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
00275 #define MODF_RVE_CALL(f_type, h, msg, src, dst, params...) \
00276         do { \
00277                 cmd=(src)[0].u.data; \
00278                 MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
00279                 ret=((f_type)cmd->function)((msg), ## params ); \
00280                 MODF_HANDLE_RETCODE(h, ret); \
00281                 /* free strings allocated by us or fixups */ \
00282                 MODF_RVE_PARAM_FREE(cmd, src, dst); \
00283         } while (0)
00284 #endif /* __SUNPRO_C */
00285 
00286 
00287 /* ret= 0! if action -> end of list(e.g DROP),
00288       > 0 to continue processing next actions
00289    and <0 on error */
00290 int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
00291 {
00292         int ret;
00293         int v;
00294         struct dest_info dst;
00295         char* tmp;
00296         char *new_uri, *end, *crt;
00297         sr31_cmd_export_t* cmd;
00298         int len;
00299         int user;
00300         struct sip_uri uri, next_hop;
00301         struct sip_uri *u;
00302         unsigned short port;
00303         str* dst_host;
00304         int i, flags;
00305         avp_t* avp;
00306         struct search_state st;
00307         struct switch_cond_table* sct;
00308         struct switch_jmp_table*  sjt;
00309         struct rval_expr* rve;
00310         struct match_cond_table* mct;
00311         struct rvalue* rv;
00312         struct rvalue* rv1;
00313         struct rval_cache c1;
00314         str s;
00315         void *srevp[2];
00316         /* temporary storage space for a struct action.val[] working copy
00317          (needed to transform RVE intro STRING before calling module
00318            functions). [0] is not used (corresp. to the module export pointer),
00319            [1] contains the number of params, and [2..] the param values.
00320            We need [1], because some fixup function use it
00321           (see fixup_get_param_count()).  */
00322         static action_u_t mod_f_params[MAX_ACTIONS];
00323 
00324         /* reset the value of error to E_UNSPEC so avoid unknowledgable
00325            functions to return with error (status<0) and not setting it
00326            leaving there previous error; cache the previous value though
00327            for functions which want to process it */
00328         prev_ser_error=ser_error;
00329         ser_error=E_UNSPEC;
00330 
00331         /* hook for every executed action (in use by cfg debugger) */
00332         if(unlikely(sr_event_enabled(SREV_CFG_RUN_ACTION)))
00333         {
00334                 srevp[0] = (void*)a;
00335                 srevp[1] = (void*)msg;
00336                 sr_event_exec(SREV_CFG_RUN_ACTION, (void*)srevp);
00337         }
00338 
00339         ret=E_BUG;
00340         switch ((unsigned char)a->type){
00341                 case DROP_T:
00342                                 switch(a->val[0].type){
00343                                         case NUMBER_ST:
00344                                                 ret=(int) a->val[0].u.number;
00345                                                 break;
00346                                         case RVE_ST:
00347                                                 rve=(struct rval_expr*)a->val[0].u.data;
00348                                                 rval_expr_eval_int(h, msg, &ret, rve);
00349                                                 break;
00350                                         case RETCODE_ST:
00351                                                 ret=h->last_retcode;
00352                                                 break;
00353                                         default:
00354                                                 BUG("unexpected subtype %d in DROP_T\n",
00355                                                                 a->val[0].type);
00356                                                 ret=0;
00357                                                 goto error;
00358                                 }
00359                                 h->run_flags|=(unsigned int)a->val[1].u.number;
00360                         break;
00361                 case FORWARD_T:
00362 #ifdef USE_TCP
00363                 case FORWARD_TCP_T:
00364 #endif
00365 #ifdef USE_TLS
00366                 case FORWARD_TLS_T:
00367 #endif
00368 #ifdef USE_SCTP
00369                 case FORWARD_SCTP_T:
00370 #endif
00371                 case FORWARD_UDP_T:
00372                         /* init dst */
00373                         init_dest_info(&dst);
00374                         if (a->type==FORWARD_UDP_T) dst.proto=PROTO_UDP;
00375 #ifdef USE_TCP
00376                         else if (a->type==FORWARD_TCP_T) dst.proto= PROTO_TCP;
00377 #endif
00378 #ifdef USE_TLS
00379                         else if (a->type==FORWARD_TLS_T) dst.proto= PROTO_TLS;
00380 #endif
00381 #ifdef USE_SCTP
00382                         else if (a->type==FORWARD_SCTP_T) dst.proto=PROTO_SCTP;
00383 #endif
00384                         else dst.proto=PROTO_NONE;
00385                         if (a->val[0].type==URIHOST_ST){
00386                                 /*parse uri*/
00387 
00388                                 if (msg->dst_uri.len) {
00389                                         ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
00390                                                                         &next_hop);
00391                                         u = &next_hop;
00392                                 } else {
00393                                         ret = parse_sip_msg_uri(msg);
00394                                         u = &msg->parsed_uri;
00395                                 }
00396 
00397                                 if (ret<0) {
00398                                         LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
00399                                                                 " dropping packet\n");
00400                                         goto error;
00401                                 }
00402 
00403                                 switch (a->val[1].type){
00404                                         case URIPORT_ST:
00405                                                                         port=u->port_no;
00406                                                                         break;
00407                                         case NUMBER_ST:
00408                                                                         port=a->val[1].u.number;
00409                                                                         break;
00410                                         default:
00411                                                         LOG(L_CRIT, "BUG: do_action bad forward 2nd"
00412                                                                                 " param type (%d)\n", a->val[1].type);
00413                                                         ret=E_UNSPEC;
00414                                                         goto error_fwd_uri;
00415                                 }
00416                                 if (dst.proto == PROTO_NONE){ /* only if proto not set get it
00417                                                                                          from the uri */
00418                                         switch(u->proto){
00419                                                 case PROTO_NONE:
00420                                                         /*dst.proto=PROTO_UDP; */
00421                                                         /* no proto, try to get it from the dns */
00422                                                         break;
00423                                                 case PROTO_UDP:
00424 #ifdef USE_TCP
00425                                                 case PROTO_TCP:
00426 #endif
00427 #ifdef USE_TLS
00428                                                 case PROTO_TLS:
00429 #endif
00430 #ifdef USE_SCTP
00431                                                 case PROTO_SCTP:
00432 #endif
00433                                                         dst.proto=u->proto;
00434                                                         break;
00435                                                 default:
00436                                                         LOG(L_ERR,"ERROR: do action: forward: bad uri"
00437                                                                         " transport %d\n", u->proto);
00438                                                         ret=E_BAD_PROTO;
00439                                                         goto error_fwd_uri;
00440                                         }
00441 #ifdef USE_TLS
00442                                         if (u->type==SIPS_URI_T){
00443                                                 if (u->proto==PROTO_UDP){
00444                                                         LOG(L_ERR, "ERROR: do_action: forward: secure uri"
00445                                                                         " incompatible with transport %d\n",
00446                                                                         u->proto);
00447                                                         ret=E_BAD_PROTO;
00448                                                         goto error_fwd_uri;
00449                                                 }
00450                                                 dst.proto=PROTO_TLS;
00451                                         }
00452 #endif
00453                                 }
00454 
00455 #ifdef HONOR_MADDR
00456                                 if (u->maddr_val.s && u->maddr_val.len)
00457                                         dst_host=&u->maddr_val;
00458                                 else
00459 #endif
00460                                         dst_host=&u->host;
00461 #ifdef USE_COMP
00462                                 dst.comp=u->comp;
00463 #endif
00464                                 ret=forward_request(msg, dst_host, port, &dst);
00465                                 if (ret>=0){
00466                                         ret=1;
00467                                 }
00468                         }else if ((a->val[0].type==PROXY_ST) && (a->val[1].type==NUMBER_ST)){
00469                                 if (dst.proto==PROTO_NONE)
00470                                         dst.proto=msg->rcv.proto;
00471                                 proxy2su(&dst.to,  (struct proxy_l*)a->val[0].u.data);
00472                                 ret=forward_request(msg, 0, 0, &dst);
00473                                 if (ret>=0){
00474                                         ret=1;
00475                                         proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
00476                                 }else if (ser_error!=E_OK){
00477                                         proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
00478                                 }
00479                         }else{
00480                                 LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
00481                                                 a->val[0].type, a->val[1].type);
00482                                 ret=E_BUG;
00483                                 goto error;
00484                         }
00485                         break;
00486                 case SEND_T:
00487                 case SEND_TCP_T:
00488                         if (a->val[0].type==URIHOST_ST){
00489                                 /*get next hop uri uri*/
00490                                 if (msg->dst_uri.len) {
00491                                         ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
00492                                                                         &next_hop);
00493                                         u = &next_hop;
00494                                 } else {
00495                                         ret = parse_sip_msg_uri(msg);
00496                                         u = &msg->parsed_uri;
00497                                 }
00498 
00499                                 if (ret<0) {
00500                                         LM_ERR("send() - bad_uri dropping packet\n");
00501                                         ret=E_BUG;
00502                                         goto error;
00503                                 }
00504                                 /* init dst */
00505                                 init_dest_info(&dst);
00506                                 ret = sip_hostport2su(&dst.to, &u->host, u->port_no,
00507                                                         &dst.proto);
00508                                 if(ret!=0) {
00509                                         LM_ERR("failed to resolve [%.*s]\n", u->host.len,
00510                                                 ZSW(u->host.s));
00511                                         ret=E_BUG;
00512                                         goto error;
00513                                 }
00514                         } else {
00515                                 if ((a->val[0].type!= PROXY_ST)|(a->val[1].type!=NUMBER_ST)){
00516                                         LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
00517                                                         a->val[0].type, a->val[1].type);
00518                                         ret=E_BUG;
00519                                         goto error;
00520                                 }
00521                                 /* init dst */
00522                                 init_dest_info(&dst);
00523                                 ret=proxy2su(&dst.to,  (struct proxy_l*)a->val[0].u.data);
00524                                 if(ret==0)
00525                                         proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
00526                         }
00527                         if (ret==0){
00528                                 if (p_onsend){
00529                                         tmp=p_onsend->buf;
00530                                         len=p_onsend->len;
00531                                 }else{
00532                                         tmp=msg->buf;
00533                                         len=msg->len;
00534                                 }
00535                                 if (a->type==SEND_T){
00536                                         /*udp*/
00537                                         dst.proto=PROTO_UDP; /* not really needed for udp_send */
00538                                         dst.send_sock=get_send_socket(msg, &dst.to, PROTO_UDP);
00539                                         if (dst.send_sock!=0){
00540                                                 ret=udp_send(&dst, tmp, len);
00541                                         }else{
00542                                                 ret=-1;
00543                                         }
00544                                 }
00545 #ifdef USE_TCP
00546                                         else{
00547                                                 /*tcp*/
00548                                                 dst.proto=PROTO_TCP;
00549                                                 dst.id=0;
00550                                                 ret=tcp_send(&dst, 0, tmp, len);
00551                                 }
00552 #endif
00553                         }else{
00554                                 ret=E_BUG;
00555                                 goto error;
00556                         }
00557                         if (ret>=0) ret=1;
00558 
00559                         break;
00560                 case LOG_T:
00561                         if ((a->val[0].type!=NUMBER_ST)|(a->val[1].type!=STRING_ST)){
00562                                 LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
00563                                                 a->val[0].type, a->val[1].type);
00564                                 ret=E_BUG;
00565                                 goto error;
00566                         }
00567                         LOG_(DEFAULT_FACILITY, a->val[0].u.number, "<script>: ", "%s", 
00568                                  a->val[1].u.string);
00569                         ret=1;
00570                         break;
00571 
00572                 /* jku -- introduce a new branch */
00573                 case APPEND_BRANCH_T:
00574                         if (unlikely(a->val[0].type!=STR_ST)) {
00575                                 LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
00576                                         a->val[0].type );
00577                                 ret=E_BUG;
00578                                 goto error;
00579                         }
00580                         getbflagsval(0, (flag_t*)&flags);
00581                         ret=append_branch(msg, &a->val[0].u.str, &msg->dst_uri,
00582                                                                 &msg->path_vec, a->val[1].u.number,
00583                                                                 (flag_t)flags, msg->force_send_socket);
00584                         /* if the uri is the ruri and q was also not changed, mark
00585                            ruri as consumed, to avoid having an identical branch */
00586                         if ((a->val[0].u.str.s == 0 || a->val[0].u.str.len == 0) &&
00587                                         a->val[1].u.number == Q_UNSPECIFIED)
00588                                 ruri_mark_consumed();
00589                         break;
00590 
00591                 /* remove last branch */
00592                 case REMOVE_BRANCH_T:
00593                         if (a->val[0].type!=NUMBER_ST) {
00594                                 ret=drop_sip_branch(0) ? -1 : 1;
00595                         } else {
00596                                 ret=drop_sip_branch(a->val[0].u.number) ? -1 : 1;
00597                         }
00598                         break;
00599 
00600                 /* remove all branches */
00601                 case CLEAR_BRANCHES_T:
00602                         clear_branches();
00603                         ret=1;
00604                         break;
00605 
00606                 /* jku begin: is_length_greater_than */
00607                 case LEN_GT_T:
00608                         if (a->val[0].type!=NUMBER_ST) {
00609                                 LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
00610                                         a->val[0].type );
00611                                 ret=E_BUG;
00612                                 goto error;
00613                         }
00614                         /* DBG("XXX: message length %d, max %d\n",
00615                                 msg->len, a->val[0].u.number ); */
00616                         ret = msg->len >= a->val[0].u.number ? 1 : -1;
00617                         break;
00618                 /* jku end: is_length_greater_than */
00619 
00620                 /* jku - begin : flag processing */
00621 
00622                 case SETFLAG_T:
00623                         if (a->val[0].type!=NUMBER_ST) {
00624                                 LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
00625                                         a->val[0].type );
00626                                 ret=E_BUG;
00627                                 goto error;
00628                         }
00629                         if (!flag_in_range( a->val[0].u.number )) {
00630                                 ret=E_CFG;
00631                                 goto error;
00632                         }
00633                         setflag( msg, a->val[0].u.number );
00634                         ret=1;
00635                         break;
00636 
00637                 case RESETFLAG_T:
00638                         if (a->val[0].type!=NUMBER_ST) {
00639                                 LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
00640                                         a->val[0].type );
00641                                 ret=E_BUG;
00642                                 goto error;
00643                         }
00644                         if (!flag_in_range( a->val[0].u.number )) {
00645                                 ret=E_CFG;
00646                                 goto error;
00647                         }
00648                         resetflag( msg, a->val[0].u.number );
00649                         ret=1;
00650                         break;
00651 
00652                 case ISFLAGSET_T:
00653                         if (a->val[0].type!=NUMBER_ST) {
00654                                 LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
00655                                         a->val[0].type );
00656                                 ret=E_BUG;
00657                                 goto error;
00658                         }
00659                         if (!flag_in_range( a->val[0].u.number )) {
00660                                 ret=E_CFG;
00661                                 goto error;
00662                         }
00663                         ret=isflagset( msg, a->val[0].u.number );
00664                         break;
00665                 /* jku - end : flag processing */
00666 
00667                 case AVPFLAG_OPER_T:
00668                         ret = 0;
00669                         if ((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL ||
00670                                         (a->val[0].u.attr->type & AVP_NAME_RE)!=0) {
00671                                 for (avp=search_first_avp(a->val[0].u.attr->type,
00672                                                         a->val[0].u.attr->name, NULL, &st);
00673                                                 avp;
00674                                                 avp = search_next_avp(&st, NULL)) {
00675                                         switch (a->val[2].u.number) {
00676                                                 /* oper: 0..reset, 1..set, -1..no change */
00677                                                 case 0:
00678                                                         avp->flags &= ~(avp_flags_t)a->val[1].u.number;
00679                                                         break;
00680                                                 case 1:
00681                                                         avp->flags |= (avp_flags_t)a->val[1].u.number;
00682                                                         break;
00683                                                 default:;
00684                                         }
00685                                         ret = ret ||
00686                                                 ((avp->flags & (avp_flags_t)a->val[1].u.number) != 0);
00687                                 }
00688                         } else {
00689                                 avp = search_avp_by_index(a->val[0].u.attr->type,
00690                                                                                         a->val[0].u.attr->name, NULL,
00691                                                                                         a->val[0].u.attr->index);
00692                                 if (avp) {
00693                                         switch (a->val[2].u.number) {
00694                                                 /* oper: 0..reset, 1..set, -1..no change */
00695                                                 case 0:
00696                                                         avp->flags &= ~(avp_flags_t)a->val[1].u.number;
00697                                                         break;
00698                                                 case 1:
00699                                                         avp->flags |= (avp_flags_t)a->val[1].u.number;
00700                                                         break;
00701                                                 default:;
00702                                         }
00703                                         ret = (avp->flags & (avp_flags_t)a->val[1].u.number) != 0;
00704                                 }
00705                         }
00706                         if (ret==0)
00707                                 ret = -1;
00708                         break;
00709                 case ERROR_T:
00710                         if ((a->val[0].type!=STRING_ST)|(a->val[1].type!=STRING_ST)){
00711                                 LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
00712                                                 a->val[0].type, a->val[1].type);
00713                                 ret=E_BUG;
00714                                 goto error;
00715                         }
00716                         LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
00717                                         "not implemented yet\n", a->val[0].u.string, a->val[1].u.string);
00718                         ret=1;
00719                         break;
00720                 case ROUTE_T:
00721                         if (likely(a->val[0].type == NUMBER_ST))
00722                                 i = a->val[0].u.number;
00723                         else if (a->val[0].type == RVE_ST) {
00724                                 rv = rval_expr_eval(h, msg, a->val[0].u.data);
00725                                 rval_cache_init(&c1);
00726                                 if (unlikely(rv == 0 ||
00727                                                 rval_get_tmp_str(h, msg, &s, rv, 0, &c1) < 0)) {
00728                                         rval_destroy(rv);
00729                                         rval_cache_clean(&c1);
00730                                         ERR("failed to convert RVE to string\n");
00731                                         ret = E_UNSPEC;
00732                                         goto error;
00733                                 }
00734                                 i = route_lookup(&main_rt, s.s);
00735                                 if (unlikely(i < 0)) {
00736                                         ERR("route \"%s\" not found at %s:%d\n",
00737                                                         s.s, (a->cfile)?a->cfile:"line", a->cline);
00738                                         rval_destroy(rv);
00739                                         rval_cache_clean(&c1);
00740                                         s.s = 0;
00741                                         ret = E_SCRIPT;
00742                                         goto error;
00743                                 }
00744                                 rval_destroy(rv);
00745                                 rval_cache_clean(&c1);
00746                                 s.s = 0;
00747                         } else {
00748                                 LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
00749                                                 a->val[0].type);
00750                                 ret=E_BUG;
00751                                 goto error;
00752                         }
00753                         if (unlikely((i>=main_rt.idx)||(i<0))){
00754                                 LOG(L_ERR, "ERROR: invalid routing table number in"
00755                                                         "route(%lu) at %s:%d\n", a->val[0].u.number,
00756                                                         (a->cfile)?a->cfile:"line", a->cline);
00757                                 ret=E_CFG;
00758                                 goto error;
00759                         }
00760                         /*ret=((ret=run_actions(rlist[a->val[0].u.number],msg))<0)?ret:1;*/
00761                         ret=run_actions(h, main_rt.rlist[i], msg);
00762                         h->last_retcode=ret;
00763                         _last_returned_code = h->last_retcode;
00764                         h->run_flags&=~(RETURN_R_F|BREAK_R_F); /* absorb return & break */
00765                         break;
00766                 case EXEC_T:
00767                         if (a->val[0].type!=STRING_ST){
00768                                 LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
00769                                                 a->val[0].type);
00770                                 ret=E_BUG;
00771                                 goto error;
00772                         }
00773                         LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
00774                                                 " using dumb version...\n", a->val[0].u.string);
00775                         ret=system(a->val[0].u.string);
00776                         if (ret!=0){
00777                                 LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
00778                         }
00779                         ret=1;
00780                         break;
00781                 case REVERT_URI_T:
00782                         if (msg->new_uri.s) {
00783                                 pkg_free(msg->new_uri.s);
00784                                 msg->new_uri.len=0;
00785                                 msg->new_uri.s=0;
00786                                 msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
00787                                 ruri_mark_new(); /* available for forking */
00788                         };
00789                         ret=1;
00790                         break;
00791                 case SET_HOST_T:
00792                 case SET_HOSTPORT_T:
00793                 case SET_HOSTPORTTRANS_T:
00794                 case SET_HOSTALL_T:
00795                 case SET_USER_T:
00796                 case SET_USERPASS_T:
00797                 case SET_PORT_T:
00798                 case SET_URI_T:
00799                 case PREFIX_T:
00800                 case STRIP_T:
00801                 case STRIP_TAIL_T:
00802                 case SET_USERPHONE_T:
00803                                 user=0;
00804                                 if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
00805                                         if (a->val[0].type!=NUMBER_ST) {
00806                                                 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
00807                                                         a->val[0].type);
00808                                                 ret=E_BUG;
00809                                                 goto error;
00810                                         }
00811                                 } else if (a->type!=SET_USERPHONE_T) {
00812                                         if (a->val[0].type!=STRING_ST) {
00813                                                 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
00814                                                         a->val[0].type);
00815                                                 ret=E_BUG;
00816                                                 goto error;
00817                                         }
00818                                 }
00819                                 if (a->type==SET_URI_T){
00820                                         if (msg->new_uri.s) {
00821                                                         pkg_free(msg->new_uri.s);
00822                                                         msg->new_uri.len=0;
00823                                         }
00824                                         msg->parsed_uri_ok=0;
00825                                         len=strlen(a->val[0].u.string);
00826                                         msg->new_uri.s=pkg_malloc(len+1);
00827                                         if (msg->new_uri.s==0){
00828                                                 LOG(L_ERR, "ERROR: do_action: memory allocation"
00829                                                                 " failure\n");
00830                                                 ret=E_OUT_OF_MEM;
00831                                                 goto error;
00832                                         }
00833                                         memcpy(msg->new_uri.s, a->val[0].u.string, len);
00834                                         msg->new_uri.s[len]=0;
00835                                         msg->new_uri.len=len;
00836                                         ruri_mark_new(); /* available for forking */
00837 
00838                                         ret=1;
00839                                         break;
00840                                 }
00841                                 if (msg->parsed_uri_ok==0) {
00842                                         if (msg->new_uri.s) {
00843                                                 tmp=msg->new_uri.s;
00844                                                 len=msg->new_uri.len;
00845                                         }else{
00846                                                 tmp=msg->first_line.u.request.uri.s;
00847                                                 len=msg->first_line.u.request.uri.len;
00848                                         }
00849                                         if (parse_uri(tmp, len, &uri)<0){
00850                                                 LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
00851                                                                         " packet\n", tmp);
00852                                                 ret=E_UNSPEC;
00853                                                 goto error;
00854                                         }
00855                                 } else {
00856                                         uri=msg->parsed_uri;
00857                                 }
00858 
00859                                 /* skip SET_USERPHONE_T action if the URI is already
00860                                  * a tel: or tels: URI, or contains the user=phone param */
00861                                 if ((a->type==SET_USERPHONE_T) 
00862                                         && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)
00863                                                 || ((uri.user_param_val.len==5) && (memcmp(uri.user_param_val.s, "phone", 5)==0)))
00864                                 ) {
00865                                         ret=1;
00866                                         break;
00867                                 }
00868                                 /* SET_PORT_T does not work with tel: URIs */
00869                                 if ((a->type==SET_PORT_T)
00870                                         && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
00871                                         && ((uri.flags & URI_SIP_USER_PHONE)==0)
00872                                 ) {
00873                                         LOG(L_ERR, "ERROR: do_action: port number of a tel: URI cannot be set\n");
00874                                         ret=E_UNSPEC;
00875                                         goto error;
00876                                 }
00877 
00878                                 new_uri=pkg_malloc(MAX_URI_SIZE);
00879                                 if (new_uri==0){
00880                                         LOG(L_ERR, "ERROR: do_action: memory allocation "
00881                                                                 " failure\n");
00882                                         ret=E_OUT_OF_MEM;
00883                                         goto error;
00884                                 }
00885                                 end=new_uri+MAX_URI_SIZE;
00886                                 crt=new_uri;
00887                                 /* begin copying */
00888                                 /* Preserve the URI scheme unless the host part needs
00889                                  * to be rewritten, and the shceme is tel: or tels: */
00890                                 switch (uri.type) {
00891                                 case SIP_URI_T:
00892                                         len=s_sip.len;
00893                                         tmp=s_sip.s;
00894                                         break;
00895 
00896                                 case SIPS_URI_T:
00897                                         len=s_sips.len;
00898                                         tmp=s_sips.s;
00899                                         break;
00900 
00901                                 case TEL_URI_T:
00902                                         if ((uri.flags & URI_SIP_USER_PHONE)
00903                                                 || (a->type==SET_HOST_T)
00904                                                 || (a->type==SET_HOSTPORT_T)
00905                                                 || (a->type==SET_HOSTPORTTRANS_T)
00906                                         ) {
00907                                                 len=s_sip.len;
00908                                                 tmp=s_sip.s;
00909                                                 break;
00910                                         }
00911                                         len=s_tel.len;
00912                                         tmp=s_tel.s;
00913                                         break;
00914 
00915                                 case TELS_URI_T:
00916                                         if ((uri.flags & URI_SIP_USER_PHONE)
00917                                                 || (a->type==SET_HOST_T)
00918                                                 || (a->type==SET_HOSTPORT_T)
00919                                                 || (a->type==SET_HOSTPORTTRANS_T)
00920                                         ) {
00921                                                 len=s_sips.len;
00922                                                 tmp=s_sips.s;
00923                                                 break;
00924                                         }
00925                                         len=s_tels.len;
00926                                         tmp=s_tels.s;
00927                                         break;
00928 
00929                                 default:
00930                                         LOG(L_ERR, "ERROR: Unsupported URI scheme (%d), "
00931                                                 "reverted to sip:\n",
00932                                                 uri.type);
00933                                         len=s_sip.len;
00934                                         tmp=s_sip.s;
00935                                 }
00936                                 if(crt+len+1 /* colon */ >end) goto error_uri;
00937                                 memcpy(crt,tmp,len);crt+=len;
00938                                 *crt=':'; crt++;
00939 
00940                                 /* user */
00941 
00942                                 /* prefix (-jiri) */
00943                                 if (a->type==PREFIX_T) {
00944                                         tmp=a->val[0].u.string;
00945                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
00946                                         memcpy(crt,tmp,len);crt+=len;
00947                                         /* whatever we had before, with prefix we have username
00948                                            now */
00949                                         user=1;
00950                                 }
00951 
00952                                 if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
00953                                         tmp=a->val[0].u.string;
00954                                         len=strlen(tmp);
00955                                 } else if (a->type==STRIP_T) {
00956                                         if (a->val[0].u.number>uri.user.len) {
00957                                                 LOG(L_WARN, "Error: too long strip asked; "
00958                                                                         " deleting username: %lu of <%.*s>\n",
00959                                                                         a->val[0].u.number, uri.user.len, uri.user.s );
00960                                                 len=0;
00961                                         } else if (a->val[0].u.number==uri.user.len) {
00962                                                 len=0;
00963                                         } else {
00964                                                 tmp=uri.user.s + a->val[0].u.number;
00965                                                 len=uri.user.len - a->val[0].u.number;
00966                                         }
00967                                 } else if (a->type==STRIP_TAIL_T) {
00968                                         if (a->val[0].u.number>uri.user.len) {
00969                                                 LOG(L_WARN, "WARNING: too long strip_tail asked; "
00970                                                                         " deleting username: %lu of <%.*s>\n",
00971                                                                         a->val[0].u.number, uri.user.len, uri.user.s );
00972                                                 len=0;
00973                                         } else if (a->val[0].u.number==uri.user.len) {
00974                                                 len=0;
00975                                         } else {
00976                                                 tmp=uri.user.s;
00977                                                 len=uri.user.len - a->val[0].u.number;
00978                                         }
00979                                 } else {
00980                                         tmp=uri.user.s;
00981                                         len=uri.user.len;
00982                                 }
00983 
00984                                 if (len){
00985                                         if(crt+len>end) goto error_uri;
00986                                         memcpy(crt,tmp,len);crt+=len;
00987                                         user=1; /* we have an user field so mark it */
00988                                 }
00989 
00990                                 if (a->type==SET_USERPASS_T) tmp=0;
00991                                 else tmp=uri.passwd.s;
00992                                 /* passwd */
00993                                 if (tmp){
00994                                         len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
00995                                         *crt=':'; crt++;
00996                                         memcpy(crt,tmp,len);crt+=len;
00997                                 }
00998                                 /* tel: URI parameters */
00999                                 if ((uri.type==TEL_URI_T)
01000                                         || (uri.type==TELS_URI_T)
01001                                 ) {
01002                                         tmp=uri.params.s;
01003                                         if (tmp){
01004                                                 len=uri.params.len; if(crt+len+1>end) goto error_uri;
01005                                                 *crt=';'; crt++;
01006                                                 memcpy(crt,tmp,len);crt+=len;
01007                                         }
01008                                 }
01009                                 /* host */
01010                                 if ((a->type==SET_HOST_T)
01011                                                 || (a->type==SET_HOSTPORT_T)
01012                                                 || (a->type==SET_HOSTALL_T)
01013                                                 || (a->type==SET_HOSTPORTTRANS_T)
01014                                 ) {
01015                                         tmp=a->val[0].u.string;
01016                                         if (tmp) len = strlen(tmp);
01017                                         else len=0;
01018                                 } else if ((uri.type==SIP_URI_T)
01019                                         || (uri.type==SIPS_URI_T)
01020                                         || (uri.flags & URI_SIP_USER_PHONE)
01021                                 ) {
01022                                         tmp=uri.host.s;
01023                                         len=uri.host.len;
01024                                 } else {
01025                                         tmp=0;
01026                                 }
01027                                 if (tmp){
01028                                         if (user) { /* add @ */
01029                                                 if(crt+1>end) goto error_uri;
01030                                                 *crt='@'; crt++;
01031                                         }
01032                                         if(crt+len>end) goto error_uri;
01033                                         memcpy(crt,tmp,len);crt+=len;
01034                                 }
01035                                 if(a->type==SET_HOSTALL_T)
01036                                         goto done_seturi;
01037                                 /* port */
01038                                 if ((a->type==SET_HOSTPORT_T)
01039                                                 || (a->type==SET_HOSTPORTTRANS_T))
01040                                         tmp=0;
01041                                 else if (a->type==SET_PORT_T) {
01042                                         tmp=a->val[0].u.string;
01043                                         if (tmp) {
01044                                                 len = strlen(tmp);
01045                                                 if(len==0) tmp = 0;
01046                                         } else len = 0;
01047                                 } else {
01048                                         tmp=uri.port.s;
01049                                         len = uri.port.len;
01050                                 }
01051                                 if (tmp){
01052                                         if(crt+len+1>end) goto error_uri;
01053                                         *crt=':'; crt++;
01054                                         memcpy(crt,tmp,len);crt+=len;
01055                                 }
01056                                 /* params */
01057                                 if ((a->type==SET_HOSTPORTTRANS_T)
01058                                         && uri.sip_params.s
01059                                         && uri.transport.s
01060                                 ) {
01061                                         /* bypass the transport parameter */
01062                                         if (uri.sip_params.s < uri.transport.s) {
01063                                                 /* there are parameters before transport */
01064                                                 len = uri.transport.s - uri.sip_params.s - 1;
01065                                                         /* ignore the ';' at the end */
01066                                                 if (crt+len+1>end) goto error_uri;
01067                                                 *crt=';'; crt++;
01068                                                 memcpy(crt,uri.sip_params.s,len);crt+=len;
01069                                         }
01070                                         len = (uri.sip_params.s + uri.sip_params.len) -
01071                                                 (uri.transport.s + uri.transport.len);
01072                                         if (len > 0) {
01073                                                 /* there are parameters after transport */
01074                                                 if (crt+len>end) goto error_uri;
01075                                                 tmp = uri.transport.s + uri.transport.len;
01076                                                 memcpy(crt,tmp,len);crt+=len;
01077                                         }
01078                                 } else {
01079                                         tmp=uri.sip_params.s;
01080                                         if (tmp){
01081                                                 len=uri.sip_params.len; if(crt+len+1>end) goto error_uri;
01082                                                 *crt=';'; crt++;
01083                                                 memcpy(crt,tmp,len);crt+=len;
01084                                         }
01085                                 }
01086                                 /* Add the user=phone param if a tel: or tels:
01087                                  * URI was converted to sip: or sips:.
01088                                  * (host part of a tel/tels URI was set.)
01089                                  * Or in case of sip: URI and SET_USERPHONE_T action */
01090                                 if (((((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
01091                                         && ((uri.flags & URI_SIP_USER_PHONE)==0))
01092                                         && ((a->type==SET_HOST_T)
01093                                                 || (a->type==SET_HOSTPORT_T)
01094                                                 || (a->type==SET_HOSTPORTTRANS_T)))
01095                                         || (a->type==SET_USERPHONE_T)
01096                                 ) {
01097                                         tmp=";user=phone";
01098                                         len=strlen(tmp);
01099                                         if(crt+len>end) goto error_uri;
01100                                         memcpy(crt,tmp,len);crt+=len;
01101                                 }
01102                                 /* headers */
01103                                 tmp=uri.headers.s;
01104                                 if (tmp){
01105                                         len=uri.headers.len; if(crt+len+1>end) goto error_uri;
01106                                         *crt='?'; crt++;
01107                                         memcpy(crt,tmp,len);crt+=len;
01108                                 }
01109         done_seturi:
01110                                 *crt=0; /* null terminate the thing */
01111                                 /* copy it to the msg */
01112                                 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
01113                                 msg->new_uri.s=new_uri;
01114                                 msg->new_uri.len=crt-new_uri;
01115                                 msg->parsed_uri_ok=0;
01116                                 ruri_mark_new(); /* available for forking */
01117                                 ret=1;
01118                                 break;
01119                 case IF_T:
01120                                         rve=(struct rval_expr*)a->val[0].u.data;
01121                                         if (unlikely(rval_expr_eval_int(h, msg, &v, rve) != 0)){
01122                                                 ERR("if expression evaluation failed (%d,%d-%d,%d)\n",
01123                                                                 rve->fpos.s_line, rve->fpos.s_col,
01124                                                                 rve->fpos.e_line, rve->fpos.e_col);
01125                                                 v=0; /* false */
01126                                         }
01127                                         if (unlikely(h->run_flags & EXIT_R_F)){
01128                                                 ret=0;
01129                                                 break;
01130                                         }
01131                                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
01132                                                                                                                             break in expr*/
01133                                         ret=1;  /*default is continue */
01134                                         if (v>0) {
01135                                                 if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
01136                                                         ret=run_actions(h,
01137                                                                                 (struct action*)a->val[1].u.data, msg);
01138                                                 }
01139                                         }else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
01140                                                         ret=run_actions(h,
01141                                                                                 (struct action*)a->val[2].u.data, msg);
01142                                         }
01143                         break;
01144                 case MODULE0_T:
01145                         MODF_CALL(cmd_function, h, msg, a->val, 0, 0);
01146                         break;
01147                 /* instead of using the parameter number, we use different names
01148                  * for calls to functions with 3, 4, 5, 6 or variable number of
01149                  * parameters due to performance reasons */
01150                 case MODULE1_T:
01151                         MODF_CALL(cmd_function, h, msg, a->val,
01152                                                                                 (char*)a->val[2].u.data,
01153                                                                                 0
01154                                         );
01155                         break;
01156                 case MODULE2_T:
01157                         MODF_CALL(cmd_function, h, msg, a->val,
01158                                                                                 (char*)a->val[2].u.data,
01159                                                                                 (char*)a->val[3].u.data
01160                                         );
01161                         break;
01162                 case MODULE3_T:
01163                         MODF_CALL(cmd_function3, h, msg, a->val,
01164                                                                                 (char*)a->val[2].u.data,
01165                                                                                 (char*)a->val[3].u.data,
01166                                                                                 (char*)a->val[4].u.data
01167                                         );
01168                         break;
01169                 case MODULE4_T:
01170                         MODF_CALL(cmd_function4, h, msg, a->val,
01171                                                                                 (char*)a->val[2].u.data,
01172                                                                                 (char*)a->val[3].u.data,
01173                                                                                 (char*)a->val[4].u.data,
01174                                                                                 (char*)a->val[5].u.data
01175                                         );
01176                         break;
01177                 case MODULE5_T:
01178                         MODF_CALL(cmd_function5, h, msg, a->val,
01179                                                                                 (char*)a->val[2].u.data,
01180                                                                                 (char*)a->val[3].u.data,
01181                                                                                 (char*)a->val[4].u.data,
01182                                                                                 (char*)a->val[5].u.data,
01183                                                                                 (char*)a->val[6].u.data
01184                                         );
01185                         break;
01186                 case MODULE6_T:
01187                         MODF_CALL(cmd_function6, h, msg, a->val,
01188                                                                                 (char*)a->val[2].u.data,
01189                                                                                 (char*)a->val[3].u.data,
01190                                                                                 (char*)a->val[4].u.data,
01191                                                                                 (char*)a->val[5].u.data,
01192                                                                                 (char*)a->val[6].u.data,
01193                                                                                 (char*)a->val[7].u.data
01194                                         );
01195                         break;
01196                 case MODULEX_T:
01197                         MODF_CALL(cmd_function_var, h, msg, a->val,
01198                                                         a->val[1].u.number, &a->val[2]);
01199                         break;
01200                 case MODULE1_RVE_T:
01201                         MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
01202                                                                                         (char*)mod_f_params[2].u.data,
01203                                                                                         0
01204                                         );
01205                         break;
01206                 case MODULE2_RVE_T:
01207                         MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
01208                                                                                         (char*)mod_f_params[2].u.data,
01209                                                                                         (char*)mod_f_params[3].u.data
01210                                         );
01211                         break;
01212                 case MODULE3_RVE_T:
01213                         MODF_RVE_CALL(cmd_function3, h, msg, a->val, mod_f_params,
01214                                                                                         (char*)mod_f_params[2].u.data,
01215                                                                                         (char*)mod_f_params[3].u.data,
01216                                                                                         (char*)mod_f_params[4].u.data
01217                                         );
01218                         break;
01219                 case MODULE4_RVE_T:
01220                         MODF_RVE_CALL(cmd_function4, h, msg, a->val, mod_f_params,
01221                                                                                         (char*)mod_f_params[2].u.data,
01222                                                                                         (char*)mod_f_params[3].u.data,
01223                                                                                         (char*)mod_f_params[4].u.data,
01224                                                                                         (char*)mod_f_params[5].u.data
01225                                         );
01226                         break;
01227                 case MODULE5_RVE_T:
01228                         MODF_RVE_CALL(cmd_function5, h, msg, a->val, mod_f_params,
01229                                                                                         (char*)mod_f_params[2].u.data,
01230                                                                                         (char*)mod_f_params[3].u.data,
01231                                                                                         (char*)mod_f_params[4].u.data,
01232                                                                                         (char*)mod_f_params[5].u.data,
01233                                                                                         (char*)mod_f_params[6].u.data
01234                                         );
01235                         break;
01236                 case MODULE6_RVE_T:
01237                         MODF_RVE_CALL(cmd_function6, h, msg, a->val, mod_f_params,
01238                                                                                         (char*)mod_f_params[2].u.data,
01239                                                                                         (char*)mod_f_params[3].u.data,
01240                                                                                         (char*)mod_f_params[4].u.data,
01241                                                                                         (char*)mod_f_params[5].u.data,
01242                                                                                         (char*)mod_f_params[6].u.data,
01243                                                                                         (char*)mod_f_params[7].u.data
01244                                         );
01245                         break;
01246                 case MODULEX_RVE_T:
01247                         MODF_RVE_CALL(cmd_function_var, h, msg, a->val, mod_f_params,
01248                                                         a->val[1].u.number, &mod_f_params[2]);
01249                         break;
01250                 case EVAL_T:
01251                         /* only eval the expression to account for possible
01252                            side-effect */
01253                         rval_expr_eval_int(h, msg, &v,
01254                                         (struct rval_expr*)a->val[0].u.data);
01255                         if (h->run_flags & EXIT_R_F){
01256                                 ret=0;
01257                                 break;
01258                         }
01259                         h->run_flags &= ~RETURN_R_F|BREAK_R_F; /* catch return & break in
01260                                                                                                           expr */
01261                         ret=1; /* default is continue */
01262                         break;
01263                 case SWITCH_COND_T:
01264                         sct=(struct switch_cond_table*)a->val[1].u.data;
01265                         if (unlikely( rval_expr_eval_int(h, msg, &v,
01266                                                                         (struct rval_expr*)a->val[0].u.data) <0)){
01267                                 /* handle error in expression => use default */
01268                                 ret=-1;
01269                                 goto sw_cond_def;
01270                         }
01271                         if (h->run_flags & EXIT_R_F){
01272                                 ret=0;
01273                                 break;
01274                         }
01275                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break
01276                                                                                                             in expr */
01277                         ret=1; /* default is continue */
01278                         for(i=0; i<sct->n; i++)
01279                                 if (sct->cond[i]==v){
01280                                         if (likely(sct->jump[i])){
01281                                                 ret=run_actions(h, sct->jump[i], msg);
01282                                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01283                                                                                                            returns passthrough */
01284                                         }
01285                                         goto skip;
01286                                 }
01287 sw_cond_def:
01288                         if (sct->def){
01289                                 ret=run_actions(h, sct->def, msg);
01290                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01291                                                                                            returns passthrough */
01292                         }
01293                         break;
01294                 case SWITCH_JT_T:
01295                         sjt=(struct switch_jmp_table*)a->val[1].u.data;
01296                         if (unlikely( rval_expr_eval_int(h, msg, &v,
01297                                                                         (struct rval_expr*)a->val[0].u.data) <0)){
01298                                 /* handle error in expression => use default */
01299                                 ret=-1;
01300                                 goto sw_jt_def;
01301                         }
01302                         if (h->run_flags & EXIT_R_F){
01303                                 ret=0;
01304                                 break;
01305                         }
01306                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break
01307                                                                                                             in expr */
01308                         ret=1; /* default is continue */
01309                         if (likely(v >= sjt->first && v <= sjt->last)){
01310                                 if (likely(sjt->tbl[v - sjt->first])){
01311                                         ret=run_actions(h, sjt->tbl[v - sjt->first], msg);
01312                                         h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01313                                                                                                    returns passthrough */
01314                                 }
01315                                 break; 
01316                         }else{
01317                                 for(i=0; i<sjt->rest.n; i++)
01318                                         if (sjt->rest.cond[i]==v){
01319                                                 if (likely(sjt->rest.jump[i])){
01320                                                         ret=run_actions(h, sjt->rest.jump[i], msg);
01321                                                         h->run_flags &= ~BREAK_R_F; /* catch breaks, but 
01322                                                                                                                    let returns pass */
01323                                                 }
01324                                                 goto skip;
01325                                         }
01326                         }
01327                         /* not found => try default */
01328 sw_jt_def:
01329                         if (sjt->rest.def){
01330                                 ret=run_actions(h, sjt->rest.def, msg);
01331                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01332                                                                                            returns passthrough */
01333                         }
01334                         break;
01335                 case BLOCK_T:
01336                         if (likely(a->val[0].u.data)){
01337                                 ret=run_actions(h, (struct action*)a->val[0].u.data, msg);
01338                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01339                                                                                            returns passthrough */
01340                         }
01341                         break;
01342                 case MATCH_COND_T:
01343                         mct=(struct match_cond_table*)a->val[1].u.data;
01344                         rval_cache_init(&c1);
01345                         rv=0;
01346                         rv1=0;
01347                         ret=rval_expr_eval_rvint(h, msg, &rv, &v, 
01348                                                                         (struct rval_expr*)a->val[0].u.data, &c1);
01349                                                                         
01350                         if (unlikely( ret<0)){
01351                                 /* handle error in expression => use default */
01352                                 ret=-1;
01353                                 goto match_cond_def;
01354                         }
01355                         if (h->run_flags & EXIT_R_F){
01356                                 ret=0;
01357                                 break;
01358                         }
01359                         h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break
01360                                                                                                             in expr */
01361                         if (likely(rv)){
01362                                 rv1=rval_convert(h, msg, RV_STR, rv, &c1);
01363                                 if (unlikely(rv1==0)){
01364                                         ret=-1;
01365                                         goto match_cond_def;
01366                                 }
01367                                 s=rv1->v.s;
01368                         }else{
01369                                 /* int result in v */
01370                                 rval_cache_clean(&c1);
01371                                 s.s=sint2str(v, &s.len);
01372                         }
01373                         ret=1; /* default is continue */
01374                         for(i=0; i<mct->n; i++)
01375                                 if (( mct->match[i].type==MATCH_STR &&
01376                                                 mct->match[i].l.s.len==s.len &&
01377                                                 memcmp(mct->match[i].l.s.s, s.s, s.len) == 0 ) ||
01378                                          ( mct->match[i].type==MATCH_RE &&
01379                                           regexec(mct->match[i].l.regex, s.s, 0, 0, 0) == 0)
01380                                         ){
01381                                         if (likely(mct->jump[i])){
01382                                                 /* make sure we cleanup first, in case run_actions()
01383                                                    exits the script directly via longjmp() */
01384                                                 if (rv1){
01385                                                         rval_destroy(rv1);
01386                                                         rval_destroy(rv);
01387                                                         rval_cache_clean(&c1);
01388                                                 }else if (rv){
01389                                                         rval_destroy(rv);
01390                                                         rval_cache_clean(&c1);
01391                                                 }
01392                                                 ret=run_actions(h, mct->jump[i], msg);
01393                                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01394                                                                                                            returns passthrough */
01395                                                 goto skip;
01396                                         }
01397                                         goto match_cleanup;
01398                                 }
01399 match_cond_def:
01400                         if (mct->def){
01401                                 /* make sure we cleanup first, in case run_actions()
01402                                    exits the script directly via longjmp() */
01403                                 if (rv1){
01404                                         rval_destroy(rv1);
01405                                         rval_destroy(rv);
01406                                         rval_cache_clean(&c1);
01407                                 }else if (rv){
01408                                         rval_destroy(rv);
01409                                         rval_cache_clean(&c1);
01410                                 }
01411                                 ret=run_actions(h, mct->def, msg);
01412                                 h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01413                                                                                            returns passthrough */
01414                                 break;
01415                         }
01416 match_cleanup:
01417                         if (rv1){
01418                                 rval_destroy(rv1);
01419                                 rval_destroy(rv);
01420                                 rval_cache_clean(&c1);
01421                         }else if (rv){
01422                                 rval_destroy(rv);
01423                                 rval_cache_clean(&c1);
01424                         }
01425                         break;
01426                 case WHILE_T:
01427                         i=0;
01428                         flags=0;
01429                         rve=(struct rval_expr*)a->val[0].u.data;
01430                         ret=1;
01431                         while(!(flags & (BREAK_R_F|RETURN_R_F|EXIT_R_F)) &&
01432                                         (rval_expr_eval_int(h, msg, &v, rve) == 0) && v){
01433                                 if (cfg_get(core, core_cfg, max_while_loops) > 0)
01434                                         i++;
01435 
01436                                 if (unlikely(i > cfg_get(core, core_cfg, max_while_loops))){
01437                                         LOG(L_ERR, "ERROR: runaway while (%d, %d): more then"
01438                                                                 " %d loops\n", 
01439                                                                 rve->fpos.s_line, rve->fpos.s_col,
01440                                                                 cfg_get(core, core_cfg, max_while_loops));
01441                                         ret=-1;
01442                                         goto error;
01443                                 }
01444                                 if (likely(a->val[1].u.data)){
01445                                         ret=run_actions(h, (struct action*)a->val[1].u.data, msg);
01446                                         flags|=h->run_flags;
01447                                         h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
01448                                                                                                    returns pass-through */
01449                                 }
01450                         }
01451                         break;
01452                 case FORCE_RPORT_T:
01453                         msg->msg_flags|=FL_FORCE_RPORT;
01454                         ret=1; /* continue processing */
01455                         break;
01456                 case ADD_LOCAL_RPORT_T:
01457                         msg->msg_flags|=FL_ADD_LOCAL_RPORT;
01458                         ret=1; /* continue processing */
01459                         break;
01460                 case UDP_MTU_TRY_PROTO_T:
01461                         msg->msg_flags|= (unsigned int)a->val[0].u.number & FL_MTU_FB_MASK;
01462                         ret=1; /* continue processing */
01463                         break;
01464                 case SET_ADV_ADDR_T:
01465                         if (a->val[0].type!=STR_ST){
01466                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
01467                                                 "type %d\n", a->val[0].type);
01468                                 ret=E_BUG;
01469                                 goto error;
01470                         }
01471                         msg->set_global_address=*((str*)a->val[0].u.data);
01472                         ret=1; /* continue processing */
01473                         break;
01474                 case SET_ADV_PORT_T:
01475                         if (a->val[0].type!=STR_ST){
01476                                 LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
01477                                                 "type %d\n", a->val[0].type);
01478                                 ret=E_BUG;
01479                                 goto error;
01480                         }
01481                         msg->set_global_port=*((str*)a->val[0].u.data);
01482                         ret=1; /* continue processing */
01483                         break;
01484 #ifdef USE_TCP
01485                 case FORCE_TCP_ALIAS_T:
01486                         if ( msg->rcv.proto==PROTO_TCP
01487 #ifdef USE_TLS
01488                                         || msg->rcv.proto==PROTO_TLS
01489 #endif
01490                            ){
01491 
01492                                 if (a->val[0].type==NOSUBTYPE)  port=msg->via1->port;
01493                                 else if (a->val[0].type==NUMBER_ST) port=(int)a->val[0].u.number;
01494                                 else{
01495                                         LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
01496                                                         " port type %d\n", a->val[0].type);
01497                                         ret=E_BUG;
01498                                         goto error;
01499                                 }
01500 
01501                                 if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
01502                                                                         msg->rcv.proto)!=0){
01503                                         LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
01504                                         ret=E_UNSPEC;
01505                                         goto error;
01506                                 }
01507                         }
01508 #endif
01509                         ret=1; /* continue processing */
01510                         break;
01511                 case FORCE_SEND_SOCKET_T:
01512                         if (a->val[0].type!=SOCKETINFO_ST){
01513                                 LOG(L_CRIT, "BUG: do_action: bad force_send_socket argument"
01514                                                 " type: %d\n", a->val[0].type);
01515                                 ret=E_BUG;
01516                                 goto error;
01517                         }
01518                         set_force_socket(msg, (struct socket_info*)a->val[0].u.data);
01519                         ret=1; /* continue processing */
01520                         break;
01521 
01522                 case ADD_T:
01523                 case ASSIGN_T:
01524                         v=lval_assign(h, msg, (struct lvalue*)a->val[0].u.data,
01525                                                                   (struct rval_expr*)a->val[1].u.data);
01526                         if (likely(v>=0))
01527                                 ret = 1;
01528                         else if (unlikely (v == EXPR_DROP)) /* hack to quit on DROP*/
01529                                 ret=0;
01530                         else
01531                                 ret=v;
01532                         break;
01533                 case SET_FWD_NO_CONNECT_T:
01534                         msg->fwd_send_flags.f|= SND_F_FORCE_CON_REUSE;
01535                         ret=1; /* continue processing */
01536                         break;
01537                 case SET_RPL_NO_CONNECT_T:
01538                         msg->rpl_send_flags.f|= SND_F_FORCE_CON_REUSE;
01539                         ret=1; /* continue processing */
01540                         break;
01541                 case SET_FWD_CLOSE_T:
01542                         msg->fwd_send_flags.f|= SND_F_CON_CLOSE;
01543                         ret=1; /* continue processing */
01544                         break;
01545                 case SET_RPL_CLOSE_T:
01546                         msg->rpl_send_flags.f|= SND_F_CON_CLOSE;
01547                         ret=1; /* continue processing */
01548                         break;
01549                 case CFG_SELECT_T:
01550                         if (a->val[0].type != CFG_GROUP_ST) {
01551                                 BUG("unsupported parameter in CFG_SELECT_T: %d\n",
01552                                                 a->val[0].type);
01553                                 ret=-1;
01554                                 goto error;
01555                         }
01556                         switch(a->val[1].type) {
01557                                 case NUMBER_ST:
01558                                         v=(int)a->val[1].u.number;
01559                                         break;
01560                                 case RVE_ST:
01561                                         if (rval_expr_eval_int(h, msg, &v, (struct rval_expr*)a->val[1].u.data) < 0) {
01562                                                 ret=-1;
01563                                                 goto error;
01564                                         }
01565                                         break;
01566                                 default:
01567                                         BUG("unsupported group id type in CFG_SELECT_T: %d\n",
01568                                                         a->val[1].type);
01569                                         ret=-1;
01570                                         goto error;
01571                         }
01572                         ret=(cfg_select((cfg_group_t*)a->val[0].u.data, v) == 0) ? 1 : -1;
01573                         break;
01574                 case CFG_RESET_T:
01575                         if (a->val[0].type != CFG_GROUP_ST) {
01576                                 BUG("unsupported parameter in CFG_RESET_T: %d\n",
01577                                                 a->val[0].type);
01578                                 ret=-1;
01579                                 goto error;
01580                         }
01581                         ret=(cfg_reset((cfg_group_t*)a->val[0].u.data) == 0) ? 1 : -1;
01582                         break;
01583 /*
01584                 default:
01585                         LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
01586 */
01587         }
01588 skip:
01589         return ret;
01590 
01591 error_uri:
01592         LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
01593         if (new_uri) pkg_free(new_uri);
01594         LM_ERR("run action error at: %s:%d\n", (a->cfile)?a->cfile:"", a->cline);
01595         return E_UNSPEC;
01596 error_fwd_uri:
01597         /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
01598 error:
01599         LM_ERR("run action error at: %s:%d\n", (a->cfile)?a->cfile:"", a->cline);
01600         return ret;
01601 }
01602 
01603 
01604 
01605 /* returns: 0, or 1 on success, <0 on error */
01606 /* (0 if drop or break encountered, 1 if not ) */
01607 int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
01608 {
01609         struct action* t;
01610         int ret;
01611         struct sr_module *mod;
01612         unsigned int ms = 0;
01613 
01614         ret=E_UNSPEC;
01615         h->rec_lev++;
01616         if (unlikely(h->rec_lev>ROUTE_MAX_REC_LEV)){
01617                 LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
01618                                         " giving up!\n", h->rec_lev);
01619                 ret=E_UNSPEC;
01620                 goto error;
01621         }
01622         if (unlikely(h->rec_lev==1)){
01623                 h->run_flags=0;
01624                 h->last_retcode=0;
01625                 _last_returned_code = h->last_retcode;
01626 #ifdef USE_LONGJMP
01627                 if (unlikely(setjmp(h->jmp_env))){
01628                         h->rec_lev=0;
01629                         ret=h->last_retcode;
01630                         goto end;
01631                 }
01632 #endif
01633         }
01634 
01635         if (unlikely(a==0)){
01636                 DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
01637                                 h->rec_lev);
01638                 ret=1;
01639         }
01640 
01641         for (t=a; t!=0; t=t->next){
01642                 if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0))
01643                         ms = TICKS_TO_MS(get_ticks_raw());
01644                 ret=do_action(h, t, msg);
01645                 if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0)) {
01646                         ms = TICKS_TO_MS(get_ticks_raw()) - ms;
01647                         if(ms >= cfg_get(core, core_cfg, latency_limit_action)) {
01648                                 LOG(cfg_get(core, core_cfg, latency_log),
01649                                                 "alert - action [%s (%d)]"
01650                                                 " cfg [%s:%d] took too long [%u ms]\n",
01651                                                 is_mod_func(t) ?
01652                                                         ((cmd_export_common_t*)(t->val[0].u.data))->name
01653                                                         : "corefunc",
01654                                                 t->type, (t->cfile)?t->cfile:"", t->cline, ms);
01655                         }
01656                 }
01657                 /* break, return or drop/exit stop execution of the current
01658                    block */
01659                 if (unlikely(h->run_flags & (BREAK_R_F|RETURN_R_F|EXIT_R_F))){
01660                         if (unlikely(h->run_flags & EXIT_R_F)) {
01661                                 h->last_retcode=ret;
01662                                 _last_returned_code = h->last_retcode;
01663 #ifdef USE_LONGJMP
01664                                 longjmp(h->jmp_env, ret);
01665 #endif
01666                         }
01667                         break;
01668                 }
01669                 /* ignore error returns */
01670         }
01671 
01672         h->rec_lev--;
01673 end:
01674         /* process module onbreak handlers if present */
01675         if (unlikely(h->rec_lev==0 && ret==0 &&
01676                                         !(h->run_flags & IGNORE_ON_BREAK_R_F)))
01677                 for (mod=modules;mod;mod=mod->next)
01678                         if (unlikely(mod->exports.onbreak_f)) {
01679                                 mod->exports.onbreak_f( msg );
01680                         }
01681         return ret;
01682 
01683 
01684 error:
01685         h->rec_lev--;
01686         return ret;
01687 }
01688 
01689 
01690 
01691 #ifdef USE_LONGJMP
01692 
01696 int run_actions_safe(struct run_act_ctx* h, struct action* a,
01697                                                 struct sip_msg* msg)
01698 {
01699         struct run_act_ctx ctx;
01700         int ret;
01701         int ign_on_break;
01702         
01703         /* start with a fresh action context */
01704         init_run_actions_ctx(&ctx);
01705         ctx.last_retcode = h->last_retcode;
01706         ign_on_break = h->run_flags & IGNORE_ON_BREAK_R_F;
01707         ctx.run_flags = h->run_flags | IGNORE_ON_BREAK_R_F;
01708         ret = run_actions(&ctx, a, msg);
01709         h->last_retcode = ctx.last_retcode;
01710         h->run_flags = (ctx.run_flags & ~IGNORE_ON_BREAK_R_F) | ign_on_break;
01711         return ret;
01712 }
01713 #endif /* USE_LONGJMP */
01714 
01715 
01716 
01717 int run_top_route(struct action* a, sip_msg_t* msg, struct run_act_ctx *c)
01718 {
01719         struct run_act_ctx ctx;
01720         struct run_act_ctx *p;
01721         int ret;
01722         flag_t sfbk;
01723 
01724         p = (c)?c:&ctx;
01725         sfbk = getsflags();
01726         setsflagsval(0);
01727         reset_static_buffer();
01728         init_run_actions_ctx(p);
01729         ret = run_actions(p, a, msg);
01730         setsflagsval(sfbk);
01731         return ret;
01732 }

Generated on Tue May 22 2012 13:10:01 for SIP Router by  doxygen 1.7.1