Coverage Report

Created: 2025-07-18 06:41

/src/kamailio/src/core/action.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *
3
 * Copyright (C) 2001-2003 FhG Fokus
4
 *
5
 * This file is part of Kamailio, a free SIP server.
6
 *
7
 * SPDX-License-Identifier: GPL-2.0-or-later
8
 *
9
 * Kamailio is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version
13
 *
14
 * Kamailio is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
 *
23
 */
24
25
/*!
26
 * \file
27
 * \brief Kamailio core :: Config file actions
28
 * \ingroup core
29
 * Module: \ref core
30
 */
31
32
33
#include "comp_defs.h"
34
35
#include "action.h"
36
#include "config.h"
37
#include "error.h"
38
#include "dprint.h"
39
#include "proxy.h"
40
#include "forward.h"
41
#include "udp_server.h"
42
#include "route.h"
43
#include "parser/msg_parser.h"
44
#include "parser/parse_uri.h"
45
#include "ut.h"
46
#include "lvalue.h"
47
#include "sr_module.h"
48
#include "select_buf.h"
49
#include "mem/mem.h"
50
#include "globals.h"
51
#include "dset.h"
52
#include "onsend.h"
53
#include "fmsg.h"
54
#include "resolve.h"
55
#ifdef USE_TCP
56
#include "tcp_server.h"
57
#endif
58
#ifdef USE_SCTP
59
#include "sctp_core.h"
60
#endif
61
#include "switch.h"
62
#include "events.h"
63
#include "cfg/cfg_struct.h"
64
65
#include <sys/types.h>
66
#include <sys/socket.h>
67
#include <netdb.h>
68
#include <stdlib.h>
69
#include <netinet/in.h>
70
#include <arpa/inet.h>
71
#include <string.h>
72
73
74
#ifdef DEBUG_DMALLOC
75
#include <dmalloc.h>
76
#endif
77
78
int _last_returned_code = 0;
79
80
/* current action executed from config file */
81
static cfg_action_t *_cfg_crt_action = 0;
82
83
/*!< maximum number of recursive calls for blocks of actions */
84
static unsigned int max_recursive_level = 256;
85
86
void set_max_recursive_level(unsigned int lev)
87
0
{
88
0
  max_recursive_level = lev;
89
0
}
90
91
/* return current action executed from config file */
92
cfg_action_t *get_cfg_crt_action(void)
93
0
{
94
0
  return _cfg_crt_action;
95
0
}
96
97
/* return line in config for current executed action */
98
int get_cfg_crt_line(void)
99
0
{
100
0
  if(_cfg_crt_action == 0)
101
0
    return 0;
102
0
  return _cfg_crt_action->cline;
103
0
}
104
105
/* return name of config for current executed action */
106
char *get_cfg_crt_file_name(void)
107
0
{
108
0
  if(_cfg_crt_action == 0)
109
0
    return 0;
110
0
  return _cfg_crt_action->cfile;
111
0
}
112
113
/* return name of routing block for current executed action */
114
char *get_cfg_crt_route_name(void)
115
0
{
116
0
  if(_cfg_crt_action == 0)
117
0
    return 0;
118
0
  return _cfg_crt_action->rname;
119
0
}
120
121
/* handle the exit code of a module function call.
122
 * (used internally in do_action())
123
 * @param h - script handle (h->last_retcode and h->run_flags will be set).
124
 * @param ret - module function (v0 or v2) retcode
125
 * Side-effects: sets _last_returned_code
126
 */
127
#define MODF_HANDLE_RETCODE(h, ret)                             \
128
0
  do {                                                        \
129
0
    /* if (unlikely((ret)==0)) (h)->run_flags|=EXIT_R_F; */ \
130
0
    (h)->run_flags |= EXIT_R_F & (((ret) != 0) - 1);        \
131
0
    (h)->last_retcode = (ret);                              \
132
0
    _last_returned_code = (h)->last_retcode;                \
133
0
  } while(0)
134
135
136
/* frees parameters converted using MODF_RVE_PARAM_CONVERT() from dst.
137
 * (used internally in do_action())
138
 * Assumes src is unchanged.
139
 * Side-effects: clobbers i (int).
140
 */
141
#define MODF_RVE_PARAM_FREE(cmd, src, dst)                                \
142
0
  for(i = 0; i < (dst)[1].u.number; i++) {                              \
143
0
    if((src)[i + 2].type == RVE_ST && (dst)[i + 2].u.data) {          \
144
0
      if((dst)[i + 2].type == RVE_FREE_FIXUP_ST) {                  \
145
0
        /* call free_fixup (which should restore the original
146
0
             string) */     \
147
0
        (void)call_fixup(                                         \
148
0
            (cmd)->free_fixup, &(dst)[i + 2].u.data, i + 1);  \
149
0
      } else if((dst)[i + 2].type == FPARAM_DYN_ST) {               \
150
0
        /* completely frees fparam and restore original string */ \
151
0
        fparam_free_restore(&(dst)[i + 2].u.data);                \
152
0
      }                                                             \
153
0
      /* free allocated string */                                   \
154
0
      pkg_free((dst)[i + 2].u.data);                                \
155
0
      (dst)[i + 2].u.data = 0;                                      \
156
0
    }                                                                 \
157
0
  }
158
159
160
/* fills dst from src, converting RVE_ST params to STRING_ST.
161
 * (used internally in do_action())
162
 * @param src - source action_u_t array, as in the action structure
163
 * @param dst - destination action_u_t array, will be filled from src.
164
 * WARNING: dst must be cleaned when done, use MODULE_RVE_PARAM_FREE()
165
 * Side-effects: clobbers i (int), s (str), rv (rvalue*), might jump to error.
166
 */
167
#define MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst)                        \
168
0
  do {                                                                     \
169
0
    (dst)[1] = (src)[1];                                                 \
170
0
    for(i = 0; i < (src)[1].u.number; i++) {                             \
171
0
      if((src)[2 + i].type == RVE_ST) {                                \
172
0
        rv = rval_expr_eval((h), (msg), (src)[i + 2].u.data);        \
173
0
        if(unlikely(rv == 0                                          \
174
0
              || rval_get_str((h), (msg), &s, rv, 0) < 0)) {   \
175
0
          rval_destroy(rv);                                        \
176
0
          ERR("failed to convert RVE to string\n");                \
177
0
          (dst)[1].u.number = i;                                   \
178
0
          MODF_RVE_PARAM_FREE(cmd, src, dst);                      \
179
0
          goto error;                                              \
180
0
        }                                                            \
181
0
        (dst)[i + 2].type = STRING_RVE_ST;                           \
182
0
        (dst)[i + 2].u.string = s.s;                                 \
183
0
        (dst)[i + 2].u.str.len = s.len;                              \
184
0
        rval_destroy(rv);                                            \
185
0
        if((cmd)->fixup) {                                           \
186
0
          if((cmd)->free_fixup) {                                  \
187
0
            if(likely(call_fixup((cmd)->fixup,                   \
188
0
                      &(dst)[i + 2].u.data, i + 1)       \
189
0
                   >= 0)) {                                  \
190
0
              /* success => mark it for calling free fixup */  \
191
0
              if(likely((dst)[i + 2].u.data != s.s))           \
192
0
                (dst)[i + 2].type = RVE_FREE_FIXUP_ST;       \
193
0
            } else {                                             \
194
0
              /* error calling fixup => mark conv. parameter \
195
0
                 and return error */ \
196
0
              (dst)[1].u.number = i;                           \
197
0
              ERR("runtime fixup failed for %s param %d\n",    \
198
0
                  (cmd)->name, i + 1);                     \
199
0
              MODF_RVE_PARAM_FREE(cmd, src, dst);              \
200
0
              goto error;                                      \
201
0
            }                                                    \
202
0
          } else if((cmd)->fixup_flags & FIXUP_F_FPARAM_RVE) {     \
203
0
            if(likely(call_fixup((cmd)->fixup,                   \
204
0
                      &(dst)[i + 2].u.data, i + 1)       \
205
0
                   >= 0)) {                                  \
206
0
              if((dst)[i + 2].u.data != s.s)                   \
207
0
                (dst)[i + 2].type = FPARAM_DYN_ST;           \
208
0
            } else {                                             \
209
0
              /* error calling fixup => mark conv. parameter \
210
0
                 and return error */ \
211
0
              (dst)[1].u.number = i;                           \
212
0
              ERR("runtime fixup failed for %s param %d\n",    \
213
0
                  (cmd)->name, i + 1);                     \
214
0
              MODF_RVE_PARAM_FREE(cmd, src, dst);              \
215
0
              goto error;                                      \
216
0
            }                                                    \
217
0
          }                                                        \
218
0
        }                                                            \
219
0
      } else                                                           \
220
0
        (dst)[i + 2] = (src)[i + 2];                                 \
221
0
    }                                                                    \
222
0
  } while(0)
223
224
225
/* call a module function with normal STRING_ST params.
226
 * (used internally in do_action())
227
 * @param f_type - cmd_function type
228
 * @param h
229
 * @param msg
230
 * @param src - source action_u_t array (e.g. action->val)
231
 * @param params... - variable list of parameters, passed to the module
232
 *               function
233
 * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), cmd,
234
 *               might jump to error.
235
 *
236
 */
237
#ifdef __SUNPRO_C
238
#define MODF_CALL(f_type, h, msg, src, ...)                \
239
  do {                                                   \
240
    cmd = (src)[0].u.data;                             \
241
    ret = ((f_type)cmd->function)((msg), __VA_ARGS__); \
242
    MODF_HANDLE_RETCODE(h, ret);                       \
243
  } while(0)
244
#else /* ! __SUNPRO_C  (gcc, icc a.s.o) */
245
#define MODF_CALL(f_type, h, msg, src, params...)       \
246
0
  do {                                                \
247
0
    cmd = (src)[0].u.data;                          \
248
0
    ret = ((f_type)cmd->function)((msg), ##params); \
249
0
    MODF_HANDLE_RETCODE(h, ret);                    \
250
0
  } while(0)
251
#endif /* __SUNPRO_C */
252
253
254
/* call a module function with possible RVE params.
255
 * (used internally in do_action())
256
 * @param f_type - cmd_function type
257
 * @param h
258
 * @param msg
259
 * @param src - source action_u_t array (e.g. action->val)
260
 * @param dst - temporary action_u_t array used for conversions. It can be
261
 *              used for the function parameters. Its contents is not
262
 *              valid after the call.
263
 * @param params... - variable list of parameters, passed to the module
264
 *               function
265
 * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), f, dst,
266
 *               might jump to error.
267
 *
268
 */
269
#ifdef __SUNPRO_C
270
#define MODF_RVE_CALL(f_type, h, msg, src, dst, ...)       \
271
  do {                                                   \
272
    cmd = (src)[0].u.data;                             \
273
    MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst);     \
274
    ret = ((f_type)cmd->function)((msg), __VA_ARGS__); \
275
    MODF_HANDLE_RETCODE(h, ret);                       \
276
    /* free strings allocated by us or fixups */       \
277
    MODF_RVE_PARAM_FREE(cmd, src, dst);                \
278
  } while(0)
279
#else /* ! __SUNPRO_C  (gcc, icc a.s.o) */
280
#define MODF_RVE_CALL(f_type, h, msg, src, dst, params...) \
281
0
  do {                                                   \
282
0
    cmd = (src)[0].u.data;                             \
283
0
    MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst);     \
284
0
    ret = ((f_type)cmd->function)((msg), ##params);    \
285
0
    MODF_HANDLE_RETCODE(h, ret);                       \
286
0
    /* free strings allocated by us or fixups */       \
287
0
    MODF_RVE_PARAM_FREE(cmd, src, dst);                \
288
0
  } while(0)
289
#endif /* __SUNPRO_C */
290
291
292
/* ret= 0! if action -> end of list(e.g DROP),
293
      > 0 to continue processing next actions
294
   and <0 on error */
295
int do_action(struct run_act_ctx *h, struct action *a, struct sip_msg *msg)
296
0
{
297
0
  int ret;
298
0
  long li;
299
0
  long v;
300
0
  struct dest_info dst;
301
0
  char *tmp;
302
0
  char *new_uri, *end, *crt;
303
0
  ksr_cmd_export_t *cmd;
304
0
  int len;
305
0
  int user;
306
0
  struct sip_uri uri, next_hop;
307
0
  struct sip_uri *u;
308
0
  unsigned short port;
309
0
  str *dst_host;
310
0
  int i, flags;
311
0
  avp_t *avp;
312
0
  struct search_state st;
313
0
  struct switch_cond_table *sct;
314
0
  struct switch_jmp_table *sjt;
315
0
  struct rval_expr *rve;
316
0
  struct match_cond_table *mct;
317
0
  struct rvalue *rv;
318
0
  struct rvalue *rv1;
319
0
  struct rval_cache c1;
320
0
  str s;
321
0
  void *srevp[2];
322
0
  sr_event_param_t evp = {0};
323
324
  /* temporary storage space for a struct action.val[] working copy
325
   (needed to transform RVE intro STRING before calling module
326
     functions). [0] is not used (corresp. to the module export pointer),
327
     [1] contains the number of params, and [2..] the param values.
328
     We need [1], because some fixup function use it
329
    (see fixup_get_param_count()).  */
330
0
  static action_u_t mod_f_params[MAX_ACTIONS];
331
332
  /* reset the value of error to E_UNSPEC so avoid unknowledgable
333
     functions to return with error (status<0) and not setting it
334
     leaving there previous error; cache the previous value though
335
     for functions which want to process it */
336
0
  prev_ser_error = ser_error;
337
0
  ser_error = E_UNSPEC;
338
339
  /* hook for every executed action (in use by cfg debugger) */
340
0
  if(unlikely(sr_event_enabled(SREV_CFG_RUN_ACTION))) {
341
0
    srevp[0] = (void *)a;
342
0
    srevp[1] = (void *)msg;
343
0
    evp.data = (void *)srevp;
344
0
    sr_event_exec(SREV_CFG_RUN_ACTION, &evp);
345
0
  }
346
347
0
  ret = E_BUG;
348
0
  switch((unsigned char)a->type) {
349
0
    case DROP_T:
350
0
      switch(a->val[0].type) {
351
0
        case NUMBER_ST:
352
0
          ret = (int)a->val[0].u.number;
353
0
          break;
354
0
        case RVE_ST:
355
0
          rve = (struct rval_expr *)a->val[0].u.data;
356
0
          if(rval_expr_eval_long(h, msg, &li, rve) < 0) {
357
0
            LM_WARN("failed to eval int expression\n");
358
0
          }
359
0
          ret = (int)li;
360
0
          break;
361
0
        case RETCODE_ST:
362
0
          ret = h->last_retcode;
363
0
          break;
364
0
        default:
365
0
          BUG("unexpected subtype %d in DROP_T\n", a->val[0].type);
366
0
          ret = 0;
367
0
          goto error;
368
0
      }
369
0
      h->run_flags |= (unsigned int)a->val[1].u.number;
370
0
      if(unlikely((ret == 0) && (h->run_flags & RETURN_R_F))) {
371
0
        h->run_flags |= EXIT_R_F;
372
0
      }
373
0
      break;
374
0
    case FORWARD_T:
375
0
#ifdef USE_TCP
376
0
    case FORWARD_TCP_T:
377
0
#endif
378
0
#ifdef USE_TLS
379
0
    case FORWARD_TLS_T:
380
0
#endif
381
0
#ifdef USE_SCTP
382
0
    case FORWARD_SCTP_T:
383
0
#endif
384
0
    case FORWARD_UDP_T:
385
      /* init dst */
386
0
      init_dest_info(&dst);
387
0
      if(a->type == FORWARD_UDP_T)
388
0
        dst.proto = PROTO_UDP;
389
0
#ifdef USE_TCP
390
0
      else if(a->type == FORWARD_TCP_T) {
391
0
        dst.proto = PROTO_TCP;
392
0
        if(msg->msg_flags & FL_USE_OTCPID) {
393
0
          dst.id = msg->otcpid;
394
0
        }
395
0
      }
396
0
#endif
397
0
#ifdef USE_TLS
398
0
      else if(a->type == FORWARD_TLS_T) {
399
0
        dst.proto = PROTO_TLS;
400
0
        if(msg->msg_flags & FL_USE_OTCPID) {
401
0
          dst.id = msg->otcpid;
402
0
        }
403
0
      }
404
0
#endif
405
0
#ifdef USE_SCTP
406
0
      else if(a->type == FORWARD_SCTP_T)
407
0
        dst.proto = PROTO_SCTP;
408
0
#endif
409
0
      else
410
0
        dst.proto = PROTO_NONE;
411
0
      if(a->val[0].type == URIHOST_ST) {
412
        /*parse uri*/
413
414
0
        if(msg->dst_uri.len) {
415
0
          ret = parse_uri(
416
0
              msg->dst_uri.s, msg->dst_uri.len, &next_hop);
417
0
          u = &next_hop;
418
0
        } else {
419
0
          ret = parse_sip_msg_uri(msg);
420
0
          u = &msg->parsed_uri;
421
0
        }
422
423
0
        if(ret < 0) {
424
0
          LM_ERR("forward: bad_uri dropping packet\n");
425
0
          goto error;
426
0
        }
427
428
0
        switch(a->val[1].type) {
429
0
          case URIPORT_ST:
430
0
            port = u->port_no;
431
0
            break;
432
0
          case NUMBER_ST:
433
0
            port = a->val[1].u.number;
434
0
            break;
435
0
          default:
436
0
            LM_CRIT("bad forward 2nd param type (%d)\n",
437
0
                a->val[1].type);
438
0
            ret = E_UNSPEC;
439
0
            goto error_fwd_uri;
440
0
        }
441
0
        if(dst.proto == PROTO_NONE) { /* only if proto not set get it
442
                       from the uri */
443
0
          switch(u->proto) {
444
0
            case PROTO_NONE:
445
              /*dst.proto=PROTO_UDP; */
446
              /* no proto, try to get it from the dns */
447
0
              break;
448
0
            case PROTO_UDP:
449
0
#ifdef USE_TCP
450
0
            case PROTO_TCP:
451
0
            case PROTO_WS:
452
0
#endif
453
0
#ifdef USE_TLS
454
0
            case PROTO_TLS:
455
0
            case PROTO_WSS:
456
0
#endif
457
0
#ifdef USE_SCTP
458
0
            case PROTO_SCTP:
459
0
#endif
460
0
              dst.proto = u->proto;
461
0
              break;
462
0
            default:
463
0
              LM_ERR("forward: bad uri transport %d\n", u->proto);
464
0
              ret = E_BAD_PROTO;
465
0
              goto error_fwd_uri;
466
0
          }
467
0
#ifdef USE_TLS
468
0
          if(u->type == SIPS_URI_T) {
469
0
            if(u->proto == PROTO_UDP) {
470
0
              LM_ERR("forward: secure uri incompatible with "
471
0
                   "transport %d\n",
472
0
                  u->proto);
473
0
              ret = E_BAD_PROTO;
474
0
              goto error_fwd_uri;
475
0
            } else if(u->proto != PROTO_WSS)
476
0
              dst.proto = PROTO_TLS;
477
0
            else
478
0
              dst.proto = PROTO_WSS;
479
0
          }
480
0
#endif
481
0
        }
482
483
#ifdef HONOR_MADDR
484
        if(u->maddr_val.s && u->maddr_val.len)
485
          dst_host = &u->maddr_val;
486
        else
487
#endif
488
0
          dst_host = &u->host;
489
#ifdef USE_COMP
490
        dst.comp = u->comp;
491
#endif
492
0
        ret = forward_request(msg, dst_host, port, &dst);
493
0
        if(ret >= 0) {
494
0
          ret = 1;
495
0
        }
496
0
      } else if((a->val[0].type == PROXY_ST)
497
0
            && (a->val[1].type == NUMBER_ST)) {
498
0
        if(dst.proto == PROTO_NONE)
499
0
          dst.proto = msg->rcv.proto;
500
0
        proxy2su(&dst.to, (struct proxy_l *)a->val[0].u.data);
501
0
        ret = forward_request(msg, 0, 0, &dst);
502
0
        if(ret >= 0) {
503
0
          ret = 1;
504
0
          proxy_mark((struct proxy_l *)a->val[0].u.data, ret);
505
0
        } else if(ser_error != E_OK) {
506
0
          proxy_mark((struct proxy_l *)a->val[0].u.data, ret);
507
0
        }
508
0
      } else {
509
0
        LM_CRIT("bad forward() types %d, %d\n", a->val[0].type,
510
0
            a->val[1].type);
511
0
        ret = E_BUG;
512
0
        goto error;
513
0
      }
514
0
      break;
515
0
    case LOG_T:
516
0
      if((a->val[0].type != NUMBER_ST) || (a->val[1].type != STRING_ST)) {
517
0
        LM_CRIT("bad log() parameter types %d, %d\n", a->val[0].type,
518
0
            a->val[1].type);
519
0
        ret = E_BUG;
520
0
        goto error;
521
0
      }
522
0
      LOG_FN(DEFAULT_FACILITY, a->val[0].u.number, "<script>: ", "%s",
523
0
          a->val[1].u.string);
524
0
      ret = 1;
525
0
      break;
526
527
    /* jku -- introduce a new branch */
528
0
    case APPEND_BRANCH_T:
529
0
      if(unlikely(a->val[0].type != STR_ST)) {
530
0
        LM_CRIT("bad append_branch_t %d\n", a->val[0].type);
531
0
        ret = E_BUG;
532
0
        goto error;
533
0
      }
534
0
      getbflagsval(0, (flag_t *)&flags);
535
0
      ret = append_branch(msg, &a->val[0].u.str, &msg->dst_uri,
536
0
          &msg->path_vec, a->val[1].u.number, (flag_t)flags,
537
0
          msg->force_send_socket, 0, 0, 0, 0);
538
      /* if the uri is the ruri and q was also not changed, mark
539
         ruri as consumed, to avoid having an identical branch */
540
0
      if((a->val[0].u.str.s == 0 || a->val[0].u.str.len == 0)
541
0
          && a->val[1].u.number == Q_UNSPECIFIED)
542
0
        ruri_mark_consumed();
543
0
      break;
544
545
    /* remove last branch */
546
0
    case REMOVE_BRANCH_T:
547
0
      if(a->val[0].type != NUMBER_ST) {
548
0
        ret = drop_sip_branch(0) ? -1 : 1;
549
0
      } else {
550
0
        ret = drop_sip_branch(a->val[0].u.number) ? -1 : 1;
551
0
      }
552
0
      break;
553
554
    /* remove all branches */
555
0
    case CLEAR_BRANCHES_T:
556
0
      clear_branches();
557
0
      ret = 1;
558
0
      break;
559
560
    /* jku begin: is_length_greater_than */
561
0
    case LEN_GT_T:
562
0
      if(a->val[0].type != NUMBER_ST) {
563
0
        LM_CRIT("bad len_gt type %d\n", a->val[0].type);
564
0
        ret = E_BUG;
565
0
        goto error;
566
0
      }
567
      /* LM_DBG("message length %d, max %d\n",
568
        msg->len, a->val[0].u.number ); */
569
0
      ret = msg->len >= a->val[0].u.number ? 1 : -1;
570
0
      break;
571
      /* jku end: is_length_greater_than */
572
573
      /* jku - begin : flag processing */
574
575
0
    case SETFLAG_T:
576
0
      if(a->val[0].type != NUMBER_ST) {
577
0
        LM_CRIT("bad setflag() type %d\n", a->val[0].type);
578
0
        ret = E_BUG;
579
0
        goto error;
580
0
      }
581
0
      if(!flag_in_range(a->val[0].u.number)) {
582
0
        ret = E_CFG;
583
0
        goto error;
584
0
      }
585
0
      setflag(msg, a->val[0].u.number);
586
0
      ret = 1;
587
0
      break;
588
589
0
    case RESETFLAG_T:
590
0
      if(a->val[0].type != NUMBER_ST) {
591
0
        LM_CRIT("bad resetflag() type %d\n", a->val[0].type);
592
0
        ret = E_BUG;
593
0
        goto error;
594
0
      }
595
0
      if(!flag_in_range(a->val[0].u.number)) {
596
0
        ret = E_CFG;
597
0
        goto error;
598
0
      }
599
0
      resetflag(msg, a->val[0].u.number);
600
0
      ret = 1;
601
0
      break;
602
603
0
    case ISFLAGSET_T:
604
0
      if(a->val[0].type != NUMBER_ST) {
605
0
        LM_CRIT("bad isflagset() type %d\n", a->val[0].type);
606
0
        ret = E_BUG;
607
0
        goto error;
608
0
      }
609
0
      if(!flag_in_range(a->val[0].u.number)) {
610
0
        ret = E_CFG;
611
0
        goto error;
612
0
      }
613
0
      ret = isflagset(msg, a->val[0].u.number);
614
0
      break;
615
      /* jku - end : flag processing */
616
617
0
    case AVPFLAG_OPER_T:
618
0
      ret = 0;
619
0
      if((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL
620
0
          || (a->val[0].u.attr->type & AVP_NAME_RE) != 0) {
621
0
        for(avp = search_first_avp(a->val[0].u.attr->type,
622
0
              a->val[0].u.attr->name, NULL, &st);
623
0
            avp; avp = search_next_avp(&st, NULL)) {
624
0
          switch(a->val[2].u.number) {
625
            /* oper: 0..reset, 1..set, -1..no change */
626
0
            case 0:
627
0
              avp->flags &= ~(avp_flags_t)a->val[1].u.number;
628
0
              break;
629
0
            case 1:
630
0
              avp->flags |= (avp_flags_t)a->val[1].u.number;
631
0
              break;
632
0
            default:;
633
0
          }
634
0
          ret = ret
635
0
              || ((avp->flags & (avp_flags_t)a->val[1].u.number)
636
0
                  != 0);
637
0
        }
638
0
      } else {
639
0
        avp = search_avp_by_index(a->val[0].u.attr->type,
640
0
            a->val[0].u.attr->name, NULL, a->val[0].u.attr->index);
641
0
        if(avp) {
642
0
          switch(a->val[2].u.number) {
643
            /* oper: 0..reset, 1..set, -1..no change */
644
0
            case 0:
645
0
              avp->flags &= ~(avp_flags_t)a->val[1].u.number;
646
0
              break;
647
0
            case 1:
648
0
              avp->flags |= (avp_flags_t)a->val[1].u.number;
649
0
              break;
650
0
            default:;
651
0
          }
652
0
          ret = (avp->flags & (avp_flags_t)a->val[1].u.number) != 0;
653
0
        }
654
0
      }
655
0
      if(ret == 0)
656
0
        ret = -1;
657
0
      break;
658
0
    case ERROR_T:
659
0
      if((a->val[0].type != STRING_ST) | (a->val[1].type != STRING_ST)) {
660
0
        LM_CRIT("bad error() types %d, %d\n", a->val[0].type,
661
0
            a->val[1].type);
662
0
        ret = E_BUG;
663
0
        goto error;
664
0
      }
665
0
      LM_NOTICE("error(\"%s\", \"%s\") "
666
0
            "not implemented yet\n",
667
0
          a->val[0].u.string, a->val[1].u.string);
668
0
      ret = 1;
669
0
      break;
670
0
    case ROUTE_T:
671
0
      if(likely(a->val[0].type == NUMBER_ST))
672
0
        i = a->val[0].u.number;
673
0
      else if(a->val[0].type == RVE_ST) {
674
0
        rv = rval_expr_eval(h, msg, a->val[0].u.data);
675
0
        rval_cache_init(&c1);
676
0
        if(unlikely(rv == 0
677
0
              || rval_get_tmp_str(h, msg, &s, rv, 0, &c1) < 0)) {
678
0
          rval_destroy(rv);
679
0
          rval_cache_clean(&c1);
680
0
          ERR("failed to convert RVE to string\n");
681
0
          ret = E_UNSPEC;
682
0
          goto error;
683
0
        }
684
0
        i = route_lookup(&main_rt, s.s);
685
0
        if(unlikely(i < 0)) {
686
0
          ERR("route \"%s\" not found at %s:%d\n", s.s,
687
0
              (a->cfile) ? a->cfile : "line", a->cline);
688
0
          rval_destroy(rv);
689
0
          rval_cache_clean(&c1);
690
0
          s.s = 0;
691
0
          ret = E_SCRIPT;
692
0
          goto error;
693
0
        }
694
0
        rval_destroy(rv);
695
0
        rval_cache_clean(&c1);
696
0
        s.s = 0;
697
0
      } else {
698
0
        LM_CRIT("bad route() type %d\n", a->val[0].type);
699
0
        ret = E_BUG;
700
0
        goto error;
701
0
      }
702
0
      if(unlikely((i >= main_rt.idx) || (i < 0))) {
703
0
        LM_ERR("invalid routing table number in"
704
0
             "route(%lu) at %s:%d\n",
705
0
            a->val[0].u.number, (a->cfile) ? a->cfile : "line",
706
0
            a->cline);
707
0
        ret = E_CFG;
708
0
        goto error;
709
0
      }
710
      /*ret=((ret=run_actions(rlist[a->val[0].u.number],msg))<0)?ret:1;*/
711
0
      ret = run_actions(h, main_rt.rlist[i], msg);
712
0
      h->last_retcode = ret;
713
0
      _last_returned_code = h->last_retcode;
714
0
      h->run_flags &=
715
0
          ~(RETURN_R_F | BREAK_R_F); /* absorb return & break */
716
0
      break;
717
0
    case EXEC_T:
718
0
      if(a->val[0].type != STRING_ST) {
719
0
        LM_CRIT("bad exec() type %d\n", a->val[0].type);
720
0
        ret = E_BUG;
721
0
        goto error;
722
0
      }
723
0
      LM_NOTICE("exec(\"%s\") not fully implemented,"
724
0
            " using dumb version...\n",
725
0
          a->val[0].u.string);
726
0
      ret = system(a->val[0].u.string);
727
0
      if(ret != 0) {
728
0
        LM_NOTICE("exec() returned %d\n", ret);
729
0
      }
730
0
      ret = 1;
731
0
      break;
732
0
    case REVERT_URI_T:
733
0
      if(msg->new_uri.s) {
734
0
        pkg_free(msg->new_uri.s);
735
0
        msg->new_uri.len = 0;
736
0
        msg->new_uri.s = 0;
737
0
        msg->parsed_uri_ok = 0; /* invalidate current parsed uri*/
738
0
        ruri_mark_new();   /* available for forking */
739
0
      };
740
0
      ret = 1;
741
0
      break;
742
0
    case SET_HOST_T:
743
0
    case SET_HOSTPORT_T:
744
0
    case SET_HOSTPORTTRANS_T:
745
0
    case SET_HOSTALL_T:
746
0
    case SET_USER_T:
747
0
    case SET_USERPASS_T:
748
0
    case SET_PORT_T:
749
0
    case SET_URI_T:
750
0
    case PREFIX_T:
751
0
    case STRIP_T:
752
0
    case STRIP_TAIL_T:
753
0
    case SET_USERPHONE_T:
754
0
      user = 0;
755
0
      if(a->type == STRIP_T || a->type == STRIP_TAIL_T) {
756
0
        if(a->val[0].type != NUMBER_ST) {
757
0
          LM_CRIT("bad set*() type %d\n", a->val[0].type);
758
0
          ret = E_BUG;
759
0
          goto error;
760
0
        }
761
0
      } else if(a->type != SET_USERPHONE_T) {
762
0
        if(a->val[0].type != STRING_ST) {
763
0
          LM_CRIT("bad set*() type %d\n", a->val[0].type);
764
0
          ret = E_BUG;
765
0
          goto error;
766
0
        }
767
0
      }
768
0
      if(a->type == SET_URI_T) {
769
0
        if(msg->new_uri.s) {
770
0
          pkg_free(msg->new_uri.s);
771
0
          msg->new_uri.len = 0;
772
0
        }
773
0
        msg->parsed_uri_ok = 0;
774
0
        len = strlen(a->val[0].u.string);
775
0
        msg->new_uri.s = pkg_malloc(len + 1);
776
0
        if(msg->new_uri.s == 0) {
777
0
          PKG_MEM_ERROR;
778
0
          ret = E_OUT_OF_MEM;
779
0
          goto error;
780
0
        }
781
0
        memcpy(msg->new_uri.s, a->val[0].u.string, len);
782
0
        msg->new_uri.s[len] = 0;
783
0
        msg->new_uri.len = len;
784
0
        ruri_mark_new(); /* available for forking */
785
786
0
        ret = 1;
787
0
        break;
788
0
      }
789
0
      if(msg->parsed_uri_ok == 0) {
790
0
        if(msg->new_uri.s) {
791
0
          tmp = msg->new_uri.s;
792
0
          len = msg->new_uri.len;
793
0
        } else {
794
0
          tmp = msg->first_line.u.request.uri.s;
795
0
          len = msg->first_line.u.request.uri.len;
796
0
        }
797
0
        if(parse_uri(tmp, len, &uri) < 0) {
798
0
          LM_ERR("bad uri <%s>, dropping packet\n", tmp);
799
0
          ret = E_UNSPEC;
800
0
          goto error;
801
0
        }
802
0
      } else {
803
0
        uri = msg->parsed_uri;
804
0
      }
805
806
      /* skip SET_USERPHONE_T action if the URI is already
807
         * a tel: or tels: URI, or contains the user=phone param */
808
0
      if((a->type == SET_USERPHONE_T)
809
0
          && ((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T)
810
0
              || ((uri.user_param_val.len == 5)
811
0
                  && (memcmp(uri.user_param_val.s, "phone", 5)
812
0
                      == 0)))) {
813
0
        ret = 1;
814
0
        break;
815
0
      }
816
      /* SET_PORT_T does not work with tel: URIs */
817
0
      if((a->type == SET_PORT_T)
818
0
          && ((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T))
819
0
          && ((uri.flags & URI_SIP_USER_PHONE) == 0)) {
820
0
        LM_ERR("port number of a tel: URI cannot be set\n");
821
0
        ret = E_UNSPEC;
822
0
        goto error;
823
0
      }
824
825
0
      new_uri = pkg_malloc(MAX_URI_SIZE);
826
0
      if(new_uri == 0) {
827
0
        PKG_MEM_ERROR;
828
0
        ret = E_OUT_OF_MEM;
829
0
        goto error;
830
0
      }
831
0
      end = new_uri + MAX_URI_SIZE;
832
0
      crt = new_uri;
833
      /* begin copying */
834
      /* Preserve the URI scheme unless the host part needs
835
         * to be rewritten, and the shceme is tel: or tels: */
836
0
      switch(uri.type) {
837
0
        case SIP_URI_T:
838
0
          len = s_sip.len;
839
0
          tmp = s_sip.s;
840
0
          break;
841
842
0
        case SIPS_URI_T:
843
0
          len = s_sips.len;
844
0
          tmp = s_sips.s;
845
0
          break;
846
847
0
        case TEL_URI_T:
848
0
          if((uri.flags & URI_SIP_USER_PHONE)
849
0
              || (a->type == SET_HOST_T)
850
0
              || (a->type == SET_HOSTPORT_T)
851
0
              || (a->type == SET_HOSTPORTTRANS_T)) {
852
0
            len = s_sip.len;
853
0
            tmp = s_sip.s;
854
0
            break;
855
0
          }
856
0
          len = s_tel.len;
857
0
          tmp = s_tel.s;
858
0
          break;
859
860
0
        case TELS_URI_T:
861
0
          if((uri.flags & URI_SIP_USER_PHONE)
862
0
              || (a->type == SET_HOST_T)
863
0
              || (a->type == SET_HOSTPORT_T)
864
0
              || (a->type == SET_HOSTPORTTRANS_T)) {
865
0
            len = s_sips.len;
866
0
            tmp = s_sips.s;
867
0
            break;
868
0
          }
869
0
          len = s_tels.len;
870
0
          tmp = s_tels.s;
871
0
          break;
872
873
0
        default:
874
0
          LM_ERR("Unsupported URI scheme (%d), reverted to sip:\n",
875
0
              uri.type);
876
0
          len = s_sip.len;
877
0
          tmp = s_sip.s;
878
0
      }
879
0
      if(crt + len + 1 /* colon */ > end)
880
0
        goto error_uri;
881
0
      memcpy(crt, tmp, len);
882
0
      crt += len;
883
0
      *crt = ':';
884
0
      crt++;
885
886
      /* user */
887
888
      /* prefix (-jiri) */
889
0
      if(a->type == PREFIX_T) {
890
0
        tmp = a->val[0].u.string;
891
0
        len = strlen(tmp);
892
0
        if(crt + len > end)
893
0
          goto error_uri;
894
0
        memcpy(crt, tmp, len);
895
0
        crt += len;
896
        /* whatever we had before, with prefix we have username
897
             now */
898
0
        user = 1;
899
0
      }
900
901
0
      if((a->type == SET_USER_T) || (a->type == SET_USERPASS_T)) {
902
0
        tmp = a->val[0].u.string;
903
0
        len = strlen(tmp);
904
0
      } else if(a->type == STRIP_T) {
905
0
        if(a->val[0].u.number > uri.user.len) {
906
0
          LM_WARN("too long strip asked; deleting username: %lu of "
907
0
              "<%.*s>\n",
908
0
              a->val[0].u.number, uri.user.len, uri.user.s);
909
0
          len = 0;
910
0
        } else if(a->val[0].u.number == uri.user.len) {
911
0
          len = 0;
912
0
        } else {
913
0
          tmp = uri.user.s + a->val[0].u.number;
914
0
          len = uri.user.len - a->val[0].u.number;
915
0
        }
916
0
      } else if(a->type == STRIP_TAIL_T) {
917
0
        if(a->val[0].u.number > uri.user.len) {
918
0
          LM_WARN("too long strip_tail asked; "
919
0
              " deleting username: %lu of <%.*s>\n",
920
0
              a->val[0].u.number, uri.user.len, uri.user.s);
921
0
          len = 0;
922
0
        } else if(a->val[0].u.number == uri.user.len) {
923
0
          len = 0;
924
0
        } else {
925
0
          tmp = uri.user.s;
926
0
          len = uri.user.len - a->val[0].u.number;
927
0
        }
928
0
      } else {
929
0
        tmp = uri.user.s;
930
0
        len = uri.user.len;
931
0
      }
932
933
0
      if(len) {
934
0
        if(crt + len > end)
935
0
          goto error_uri;
936
0
        memcpy(crt, tmp, len);
937
0
        crt += len;
938
0
        user = 1; /* we have a user field so mark it */
939
0
      }
940
941
0
      if(a->type == SET_USERPASS_T)
942
0
        tmp = 0;
943
0
      else
944
0
        tmp = uri.passwd.s;
945
      /* passwd - keep it only if user is set */
946
0
      if(user && tmp) {
947
0
        len = uri.passwd.len;
948
0
        if(crt + len + 1 > end)
949
0
          goto error_uri;
950
0
        *crt = ':';
951
0
        crt++;
952
0
        memcpy(crt, tmp, len);
953
0
        crt += len;
954
0
      }
955
      /* tel: URI parameters */
956
0
      if((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T)) {
957
0
        tmp = uri.params.s;
958
0
        if(tmp) {
959
0
          len = uri.params.len;
960
0
          if(crt + len + 1 > end)
961
0
            goto error_uri;
962
0
          *crt = ';';
963
0
          crt++;
964
0
          memcpy(crt, tmp, len);
965
0
          crt += len;
966
0
        }
967
0
      }
968
      /* host */
969
0
      if((a->type == SET_HOST_T) || (a->type == SET_HOSTPORT_T)
970
0
          || (a->type == SET_HOSTALL_T)
971
0
          || (a->type == SET_HOSTPORTTRANS_T)) {
972
0
        tmp = a->val[0].u.string;
973
0
        if(tmp)
974
0
          len = strlen(tmp);
975
0
        else
976
0
          len = 0;
977
0
      } else if((uri.type == SIP_URI_T) || (uri.type == SIPS_URI_T)
978
0
            || (uri.flags & URI_SIP_USER_PHONE)) {
979
0
        tmp = uri.host.s;
980
0
        len = uri.host.len;
981
0
      } else {
982
0
        tmp = 0;
983
0
      }
984
0
      if(tmp) {
985
0
        if(user) { /* add @ */
986
0
          if(crt + 1 > end)
987
0
            goto error_uri;
988
0
          *crt = '@';
989
0
          crt++;
990
0
        }
991
0
        if(crt + len > end)
992
0
          goto error_uri;
993
0
        memcpy(crt, tmp, len);
994
0
        crt += len;
995
0
      }
996
0
      if(a->type == SET_HOSTALL_T)
997
0
        goto done_seturi;
998
      /* port */
999
0
      if((a->type == SET_HOSTPORT_T) || (a->type == SET_HOSTPORTTRANS_T))
1000
0
        tmp = 0;
1001
0
      else if(a->type == SET_PORT_T) {
1002
0
        tmp = a->val[0].u.string;
1003
0
        if(tmp) {
1004
0
          len = strlen(tmp);
1005
0
          if(len == 0)
1006
0
            tmp = 0;
1007
0
        } else
1008
0
          len = 0;
1009
0
      } else {
1010
0
        tmp = uri.port.s;
1011
0
        len = uri.port.len;
1012
0
      }
1013
0
      if(tmp) {
1014
0
        if(crt + len + 1 > end)
1015
0
          goto error_uri;
1016
0
        *crt = ':';
1017
0
        crt++;
1018
0
        memcpy(crt, tmp, len);
1019
0
        crt += len;
1020
0
      }
1021
      /* params */
1022
0
      if((a->type == SET_HOSTPORTTRANS_T) && uri.sip_params.s
1023
0
          && uri.transport.s) {
1024
        /* bypass the transport parameter */
1025
0
        if(uri.sip_params.s < uri.transport.s) {
1026
          /* there are parameters before transport */
1027
0
          len = uri.transport.s - uri.sip_params.s - 1;
1028
          /* ignore the ';' at the end */
1029
0
          if(crt + len + 1 > end)
1030
0
            goto error_uri;
1031
0
          *crt = ';';
1032
0
          crt++;
1033
0
          memcpy(crt, uri.sip_params.s, len);
1034
0
          crt += len;
1035
0
        }
1036
0
        len = (uri.sip_params.s + uri.sip_params.len)
1037
0
            - (uri.transport.s + uri.transport.len);
1038
0
        if(len > 0) {
1039
          /* there are parameters after transport */
1040
0
          if(crt + len > end)
1041
0
            goto error_uri;
1042
0
          tmp = uri.transport.s + uri.transport.len;
1043
0
          memcpy(crt, tmp, len);
1044
0
          crt += len;
1045
0
        }
1046
0
      } else {
1047
0
        tmp = uri.sip_params.s;
1048
0
        if(tmp) {
1049
0
          len = uri.sip_params.len;
1050
0
          if(crt + len + 1 > end)
1051
0
            goto error_uri;
1052
0
          *crt = ';';
1053
0
          crt++;
1054
0
          memcpy(crt, tmp, len);
1055
0
          crt += len;
1056
0
        }
1057
0
      }
1058
      /* Add the user=phone param if a tel: or tels:
1059
         * URI was converted to sip: or sips:.
1060
         * (host part of a tel/tels URI was set.)
1061
         * Or in case of sip: URI and SET_USERPHONE_T action */
1062
0
      if(((((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T))
1063
0
            && ((uri.flags & URI_SIP_USER_PHONE) == 0))
1064
0
             && ((a->type == SET_HOST_T)
1065
0
                 || (a->type == SET_HOSTPORT_T)
1066
0
                 || (a->type == SET_HOSTPORTTRANS_T)))
1067
0
          || (a->type == SET_USERPHONE_T)) {
1068
0
        tmp = ";user=phone";
1069
0
        len = strlen(tmp);
1070
0
        if(crt + len > end)
1071
0
          goto error_uri;
1072
0
        memcpy(crt, tmp, len);
1073
0
        crt += len;
1074
0
      }
1075
      /* headers */
1076
0
      tmp = uri.headers.s;
1077
0
      if(tmp) {
1078
0
        len = uri.headers.len;
1079
0
        if(crt + len + 1 > end)
1080
0
          goto error_uri;
1081
0
        *crt = '?';
1082
0
        crt++;
1083
0
        memcpy(crt, tmp, len);
1084
0
        crt += len;
1085
0
      }
1086
0
    done_seturi:
1087
0
      *crt = 0; /* null terminate the thing */
1088
      /* copy it to the msg */
1089
0
      if(msg->new_uri.s)
1090
0
        pkg_free(msg->new_uri.s);
1091
0
      msg->new_uri.s = new_uri;
1092
0
      msg->new_uri.len = crt - new_uri;
1093
0
      msg->parsed_uri_ok = 0;
1094
0
      ruri_mark_new(); /* available for forking */
1095
0
      ret = 1;
1096
0
      break;
1097
0
    case IF_T:
1098
0
      rve = (struct rval_expr *)a->val[0].u.data;
1099
0
      if(unlikely(rval_expr_eval_long(h, msg, &v, rve) != 0)) {
1100
0
        ERR("if expression evaluation failed (%d,%d-%d,%d)\n",
1101
0
            rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line,
1102
0
            rve->fpos.e_col);
1103
0
        v = 0; /* false */
1104
0
      }
1105
0
      if(unlikely(h->run_flags & EXIT_R_F)) {
1106
0
        ret = 0;
1107
0
        break;
1108
0
      }
1109
0
      h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return &
1110
                                  break in expr*/
1111
0
      ret = 1;                   /*default is continue */
1112
0
      if((ksr_return_mode == 0 && v > 0)
1113
0
          || (ksr_return_mode != 0 && v != 0)) {
1114
0
        if((a->val[1].type == ACTIONS_ST) && a->val[1].u.data) {
1115
0
          ret = run_actions(
1116
0
              h, (struct action *)a->val[1].u.data, msg);
1117
0
        }
1118
0
      } else if((a->val[2].type == ACTIONS_ST) && a->val[2].u.data) {
1119
0
        ret = run_actions(h, (struct action *)a->val[2].u.data, msg);
1120
0
      }
1121
0
      break;
1122
0
    case MODULE0_T:
1123
0
      MODF_CALL(cmd_function, h, msg, a->val, 0, 0);
1124
0
      break;
1125
    /* instead of using the parameter number, we use different names
1126
     * for calls to functions with 3, 4, 5, 6 or variable number of
1127
     * parameters due to performance reasons */
1128
0
    case MODULE1_T:
1129
0
      MODF_CALL(
1130
0
          cmd_function, h, msg, a->val, (char *)a->val[2].u.data, 0);
1131
0
      break;
1132
0
    case MODULE2_T:
1133
0
      MODF_CALL(cmd_function, h, msg, a->val, (char *)a->val[2].u.data,
1134
0
          (char *)a->val[3].u.data);
1135
0
      break;
1136
0
    case MODULE3_T:
1137
0
      MODF_CALL(cmd_function3, h, msg, a->val, (char *)a->val[2].u.data,
1138
0
          (char *)a->val[3].u.data, (char *)a->val[4].u.data);
1139
0
      break;
1140
0
    case MODULE4_T:
1141
0
      MODF_CALL(cmd_function4, h, msg, a->val, (char *)a->val[2].u.data,
1142
0
          (char *)a->val[3].u.data, (char *)a->val[4].u.data,
1143
0
          (char *)a->val[5].u.data);
1144
0
      break;
1145
0
    case MODULE5_T:
1146
0
      MODF_CALL(cmd_function5, h, msg, a->val, (char *)a->val[2].u.data,
1147
0
          (char *)a->val[3].u.data, (char *)a->val[4].u.data,
1148
0
          (char *)a->val[5].u.data, (char *)a->val[6].u.data);
1149
0
      break;
1150
0
    case MODULE6_T:
1151
0
      MODF_CALL(cmd_function6, h, msg, a->val, (char *)a->val[2].u.data,
1152
0
          (char *)a->val[3].u.data, (char *)a->val[4].u.data,
1153
0
          (char *)a->val[5].u.data, (char *)a->val[6].u.data,
1154
0
          (char *)a->val[7].u.data);
1155
0
      break;
1156
0
    case MODULEX_T:
1157
0
      MODF_CALL(cmd_function_var, h, msg, a->val, a->val[1].u.number,
1158
0
          &a->val[2]);
1159
0
      break;
1160
0
    case MODULE1_RVE_T:
1161
0
      MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
1162
0
          (char *)mod_f_params[2].u.data, 0);
1163
0
      break;
1164
0
    case MODULE2_RVE_T:
1165
0
      MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
1166
0
          (char *)mod_f_params[2].u.data,
1167
0
          (char *)mod_f_params[3].u.data);
1168
0
      break;
1169
0
    case MODULE3_RVE_T:
1170
0
      MODF_RVE_CALL(cmd_function3, h, msg, a->val, mod_f_params,
1171
0
          (char *)mod_f_params[2].u.data,
1172
0
          (char *)mod_f_params[3].u.data,
1173
0
          (char *)mod_f_params[4].u.data);
1174
0
      break;
1175
0
    case MODULE4_RVE_T:
1176
0
      MODF_RVE_CALL(cmd_function4, h, msg, a->val, mod_f_params,
1177
0
          (char *)mod_f_params[2].u.data,
1178
0
          (char *)mod_f_params[3].u.data,
1179
0
          (char *)mod_f_params[4].u.data,
1180
0
          (char *)mod_f_params[5].u.data);
1181
0
      break;
1182
0
    case MODULE5_RVE_T:
1183
0
      MODF_RVE_CALL(cmd_function5, h, msg, a->val, mod_f_params,
1184
0
          (char *)mod_f_params[2].u.data,
1185
0
          (char *)mod_f_params[3].u.data,
1186
0
          (char *)mod_f_params[4].u.data,
1187
0
          (char *)mod_f_params[5].u.data,
1188
0
          (char *)mod_f_params[6].u.data);
1189
0
      break;
1190
0
    case MODULE6_RVE_T:
1191
0
      MODF_RVE_CALL(cmd_function6, h, msg, a->val, mod_f_params,
1192
0
          (char *)mod_f_params[2].u.data,
1193
0
          (char *)mod_f_params[3].u.data,
1194
0
          (char *)mod_f_params[4].u.data,
1195
0
          (char *)mod_f_params[5].u.data,
1196
0
          (char *)mod_f_params[6].u.data,
1197
0
          (char *)mod_f_params[7].u.data);
1198
0
      break;
1199
0
    case MODULEX_RVE_T:
1200
0
      MODF_RVE_CALL(cmd_function_var, h, msg, a->val, mod_f_params,
1201
0
          a->val[1].u.number, &mod_f_params[2]);
1202
0
      break;
1203
0
    case EVAL_T:
1204
      /* only eval the expression to account for possible
1205
         side-effect */
1206
0
      rval_expr_eval_long(
1207
0
          h, msg, &v, (struct rval_expr *)a->val[0].u.data);
1208
0
      if(h->run_flags & EXIT_R_F) {
1209
0
        ret = 0;
1210
0
        break;
1211
0
      }
1212
0
      h->run_flags &= ~RETURN_R_F | BREAK_R_F; /* catch return & break in
1213
                            expr */
1214
0
      ret = 1;                 /* default is continue */
1215
0
      break;
1216
0
    case SWITCH_COND_T:
1217
0
      sct = (struct switch_cond_table *)a->val[1].u.data;
1218
0
      if(unlikely(rval_expr_eval_long(h, msg, &v,
1219
0
                (struct rval_expr *)a->val[0].u.data)
1220
0
            < 0)) {
1221
        /* handle error in expression => use default */
1222
0
        ret = -1;
1223
0
        goto sw_cond_def;
1224
0
      }
1225
0
      if(h->run_flags & EXIT_R_F) {
1226
0
        ret = 0;
1227
0
        break;
1228
0
      }
1229
0
      h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return & break
1230
                              in expr */
1231
0
      ret = 1;                   /* default is continue */
1232
0
      for(i = 0; i < sct->n; i++)
1233
0
        if(sct->cond[i] == v) {
1234
0
          if(likely(sct->jump[i])) {
1235
0
            ret = run_actions(h, sct->jump[i], msg);
1236
0
            h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1237
                             returns passthrough */
1238
0
          }
1239
0
          goto skip;
1240
0
        }
1241
0
    sw_cond_def:
1242
0
      if(sct->def) {
1243
0
        ret = run_actions(h, sct->def, msg);
1244
0
        h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1245
                         returns passthrough */
1246
0
      }
1247
0
      break;
1248
0
    case SWITCH_JT_T:
1249
0
      sjt = (struct switch_jmp_table *)a->val[1].u.data;
1250
0
      if(unlikely(rval_expr_eval_long(h, msg, &v,
1251
0
                (struct rval_expr *)a->val[0].u.data)
1252
0
            < 0)) {
1253
        /* handle error in expression => use default */
1254
0
        ret = -1;
1255
0
        goto sw_jt_def;
1256
0
      }
1257
0
      if(h->run_flags & EXIT_R_F) {
1258
0
        ret = 0;
1259
0
        break;
1260
0
      }
1261
0
      h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return & break
1262
                              in expr */
1263
0
      ret = 1;                   /* default is continue */
1264
0
      if(likely(v >= sjt->first && v <= sjt->last)) {
1265
0
        if(likely(sjt->tbl[v - sjt->first])) {
1266
0
          ret = run_actions(h, sjt->tbl[v - sjt->first], msg);
1267
0
          h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1268
                           returns passthrough */
1269
0
        }
1270
0
        break;
1271
0
      } else {
1272
0
        for(i = 0; i < sjt->rest.n; i++)
1273
0
          if(sjt->rest.cond[i] == v) {
1274
0
            if(likely(sjt->rest.jump[i])) {
1275
0
              ret = run_actions(h, sjt->rest.jump[i], msg);
1276
0
              h->run_flags &= ~BREAK_R_F; /* catch breaks, but
1277
                               let returns pass */
1278
0
            }
1279
0
            goto skip;
1280
0
          }
1281
0
      }
1282
      /* not found => try default */
1283
0
    sw_jt_def:
1284
0
      if(sjt->rest.def) {
1285
0
        ret = run_actions(h, sjt->rest.def, msg);
1286
0
        h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1287
                         returns passthrough */
1288
0
      }
1289
0
      break;
1290
0
    case BLOCK_T:
1291
0
      if(likely(a->val[0].u.data)) {
1292
0
        ret = run_actions(h, (struct action *)a->val[0].u.data, msg);
1293
0
        h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1294
                         returns passthrough */
1295
0
      }
1296
0
      break;
1297
0
    case MATCH_COND_T:
1298
0
      mct = (struct match_cond_table *)a->val[1].u.data;
1299
0
      rval_cache_init(&c1);
1300
0
      rv = 0;
1301
0
      rv1 = 0;
1302
0
      ret = rval_expr_eval_rvlong(
1303
0
          h, msg, &rv, &v, (struct rval_expr *)a->val[0].u.data, &c1);
1304
1305
0
      if(unlikely(ret < 0)) {
1306
        /* handle error in expression => use default */
1307
0
        ret = -1;
1308
0
        goto match_cond_def;
1309
0
      }
1310
0
      if(h->run_flags & EXIT_R_F) {
1311
0
        ret = 0;
1312
0
        break;
1313
0
      }
1314
0
      h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return & break
1315
                              in expr */
1316
0
      if(likely(rv)) {
1317
0
        rv1 = rval_convert(h, msg, RV_STR, rv, &c1);
1318
0
        if(unlikely(rv1 == 0)) {
1319
0
          ret = -1;
1320
0
          goto match_cond_def;
1321
0
        }
1322
0
        s = rv1->v.s;
1323
0
      } else {
1324
        /* int result in v */
1325
0
        rval_cache_clean(&c1);
1326
0
        s.s = sint2str(v, &s.len);
1327
0
      }
1328
0
      ret = 1; /* default is continue */
1329
0
      for(i = 0; i < mct->n; i++)
1330
0
        if((mct->match[i].type == MATCH_STR
1331
0
               && mct->match[i].l.s.len == s.len
1332
0
               && memcmp(mct->match[i].l.s.s, s.s, s.len) == 0)
1333
0
            || (mct->match[i].type == MATCH_RE
1334
0
                && regexec(mct->match[i].l.regex, s.s, 0, 0, 0)
1335
0
                       == 0)) {
1336
0
          if(likely(mct->jump[i])) {
1337
            /* make sure we cleanup first, in case run_actions()
1338
               exits the script directly via longjmp() */
1339
0
            if(rv1) {
1340
0
              rval_destroy(rv1);
1341
0
              rval_destroy(rv);
1342
0
              rval_cache_clean(&c1);
1343
0
            } else if(rv) {
1344
0
              rval_destroy(rv);
1345
0
              rval_cache_clean(&c1);
1346
0
            }
1347
0
            ret = run_actions(h, mct->jump[i], msg);
1348
0
            h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1349
                             returns passthrough */
1350
0
            goto skip;
1351
0
          }
1352
0
          goto match_cleanup;
1353
0
        }
1354
0
    match_cond_def:
1355
0
      if(mct->def) {
1356
        /* make sure we cleanup first, in case run_actions()
1357
           exits the script directly via longjmp() */
1358
0
        if(rv1) {
1359
0
          rval_destroy(rv1);
1360
0
          rval_destroy(rv);
1361
0
          rval_cache_clean(&c1);
1362
0
        } else if(rv) {
1363
0
          rval_destroy(rv);
1364
0
          rval_cache_clean(&c1);
1365
0
        }
1366
0
        ret = run_actions(h, mct->def, msg);
1367
0
        h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1368
                         returns passthrough */
1369
0
        break;
1370
0
      }
1371
0
    match_cleanup:
1372
0
      if(rv1) {
1373
0
        rval_destroy(rv1);
1374
0
        rval_destroy(rv);
1375
0
        rval_cache_clean(&c1);
1376
0
      } else if(rv) {
1377
0
        rval_destroy(rv);
1378
0
        rval_cache_clean(&c1);
1379
0
      }
1380
0
      break;
1381
0
    case WHILE_T:
1382
0
      i = 0;
1383
0
      flags = 0;
1384
0
      rve = (struct rval_expr *)a->val[0].u.data;
1385
0
      ret = 1;
1386
0
      while(!(flags & (BREAK_R_F | RETURN_R_F | EXIT_R_F))
1387
0
          && (rval_expr_eval_long(h, msg, &v, rve) == 0)
1388
0
          && ((ksr_return_mode == 0 && v > 0)
1389
0
              || (ksr_return_mode != 0 && v != 0))) {
1390
0
        if(cfg_get(core, core_cfg, max_while_loops) > 0)
1391
0
          i++;
1392
1393
0
        if(unlikely(i > cfg_get(core, core_cfg, max_while_loops))) {
1394
0
          LM_ERR("runaway while (%d, %d): more than %d loops\n",
1395
0
              rve->fpos.s_line, rve->fpos.s_col,
1396
0
              cfg_get(core, core_cfg, max_while_loops));
1397
0
          ret = -1;
1398
0
          goto error;
1399
0
        }
1400
0
        if(likely(a->val[1].u.data)) {
1401
0
          ret = run_actions(
1402
0
              h, (struct action *)a->val[1].u.data, msg);
1403
0
          flags |= h->run_flags;
1404
0
          h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
1405
                           returns pass-through */
1406
0
        }
1407
0
      }
1408
0
      break;
1409
0
    case FORCE_RPORT_T:
1410
0
      msg->msg_flags |= FL_FORCE_RPORT;
1411
0
      ret = 1; /* continue processing */
1412
0
      break;
1413
0
    case ADD_LOCAL_RPORT_T:
1414
0
      msg->msg_flags |= FL_ADD_LOCAL_RPORT;
1415
0
      ret = 1; /* continue processing */
1416
0
      break;
1417
0
    case UDP_MTU_TRY_PROTO_T:
1418
0
      msg->msg_flags |= (msg_flags_t)a->val[0].u.number & FL_MTU_FB_MASK;
1419
0
      ret = 1; /* continue processing */
1420
0
      break;
1421
0
    case SET_ADV_ADDR_T:
1422
0
      if(a->val[0].type != STR_ST) {
1423
0
        LM_CRIT("bad set_advertised_address() type %d\n",
1424
0
            a->val[0].type);
1425
0
        ret = E_BUG;
1426
0
        goto error;
1427
0
      }
1428
0
      msg->set_global_address = *((str *)a->val[0].u.data);
1429
0
      ret = 1; /* continue processing */
1430
0
      break;
1431
0
    case SET_ADV_PORT_T:
1432
0
      if(a->val[0].type != STR_ST) {
1433
0
        LM_CRIT("bad set_advertised_port() type %d\n", a->val[0].type);
1434
0
        ret = E_BUG;
1435
0
        goto error;
1436
0
      }
1437
0
      msg->set_global_port = *((str *)a->val[0].u.data);
1438
0
      ret = 1; /* continue processing */
1439
0
      break;
1440
0
#ifdef USE_TCP
1441
0
    case FORCE_TCP_ALIAS_T:
1442
0
      if(msg->rcv.proto == PROTO_TCP
1443
0
#ifdef USE_TLS
1444
0
          || msg->rcv.proto == PROTO_TLS
1445
0
#endif
1446
0
      ) {
1447
1448
0
        if(a->val[0].type == NOSUBTYPE)
1449
0
          port = msg->via1->port;
1450
0
        else if(a->val[0].type == NUMBER_ST)
1451
0
          port = (int)a->val[0].u.number;
1452
0
        else {
1453
0
          LM_CRIT("bad force_tcp_alias"
1454
0
              " port type %d\n",
1455
0
              a->val[0].type);
1456
0
          ret = E_BUG;
1457
0
          goto error;
1458
0
        }
1459
1460
0
        if(tcpconn_add_alias(
1461
0
               msg->rcv.proto_reserved1, port, msg->rcv.proto)
1462
0
            != 0) {
1463
0
          LM_ERR("receive_msg: tcp alias failed\n");
1464
0
          ret = E_UNSPEC;
1465
0
          goto error;
1466
0
        }
1467
0
      }
1468
0
#endif
1469
0
      ret = 1; /* continue processing */
1470
0
      break;
1471
0
    case FORCE_SEND_SOCKET_T:
1472
0
      if(a->val[0].type != SOCKETINFO_ST) {
1473
0
        LM_CRIT("bad force_send_socket argument"
1474
0
            " type: %d\n",
1475
0
            a->val[0].type);
1476
0
        ret = E_BUG;
1477
0
        goto error;
1478
0
      }
1479
0
      LM_DBG("setting send-socket to [%.*s]\n",
1480
0
          ((struct socket_info *)a->val[0].u.data)->sock_str.len,
1481
0
          ((struct socket_info *)a->val[0].u.data)->sock_str.s);
1482
0
      set_force_socket(msg, (struct socket_info *)a->val[0].u.data);
1483
0
      ret = 1; /* continue processing */
1484
0
      break;
1485
1486
0
    case ADD_T:
1487
0
    case ASSIGN_T:
1488
0
      v = lval_assign(h, msg, (struct lvalue *)a->val[0].u.data,
1489
0
          (struct rval_expr *)a->val[1].u.data);
1490
0
      if(likely(v >= 0))
1491
0
        ret = 1;
1492
0
      else if(unlikely(v == EXPR_DROP)) /* hack to quit on DROP*/
1493
0
        ret = 0;
1494
0
      else
1495
0
        ret = v;
1496
0
      break;
1497
0
    case SET_FWD_NO_CONNECT_T:
1498
0
      msg->fwd_send_flags.f |= SND_F_FORCE_CON_REUSE;
1499
0
      ret = 1; /* continue processing */
1500
0
      break;
1501
0
    case SET_RPL_NO_CONNECT_T:
1502
0
      msg->rpl_send_flags.f |= SND_F_FORCE_CON_REUSE;
1503
0
      ret = 1; /* continue processing */
1504
0
      break;
1505
0
    case SET_FWD_CLOSE_T:
1506
0
      msg->fwd_send_flags.f |= SND_F_CON_CLOSE;
1507
0
      ret = 1; /* continue processing */
1508
0
      break;
1509
0
    case SET_RPL_CLOSE_T:
1510
0
      msg->rpl_send_flags.f |= SND_F_CON_CLOSE;
1511
0
      ret = 1; /* continue processing */
1512
0
      break;
1513
0
    case CFG_SELECT_T:
1514
0
      if(a->val[0].type != CFG_GROUP_ST) {
1515
0
        BUG("unsupported parameter in CFG_SELECT_T: %d\n",
1516
0
            a->val[0].type);
1517
0
        ret = -1;
1518
0
        goto error;
1519
0
      }
1520
0
      switch(a->val[1].type) {
1521
0
        case NUMBER_ST:
1522
0
          v = (int)a->val[1].u.number;
1523
0
          break;
1524
0
        case RVE_ST:
1525
0
          if(rval_expr_eval_long(
1526
0
                 h, msg, &v, (struct rval_expr *)a->val[1].u.data)
1527
0
              < 0) {
1528
0
            ret = -1;
1529
0
            goto error;
1530
0
          }
1531
0
          break;
1532
0
        default:
1533
0
          BUG("unsupported group id type in CFG_SELECT_T: %d\n",
1534
0
              a->val[1].type);
1535
0
          ret = -1;
1536
0
          goto error;
1537
0
      }
1538
0
      ret = (cfg_select((cfg_group_t *)a->val[0].u.data, v) == 0) ? 1
1539
0
                                    : -1;
1540
0
      break;
1541
0
    case CFG_RESET_T:
1542
0
      if(a->val[0].type != CFG_GROUP_ST) {
1543
0
        BUG("unsupported parameter in CFG_RESET_T: %d\n",
1544
0
            a->val[0].type);
1545
0
        ret = -1;
1546
0
        goto error;
1547
0
      }
1548
0
      ret = (cfg_reset((cfg_group_t *)a->val[0].u.data) == 0) ? 1 : -1;
1549
0
      break;
1550
      /*
1551
    default:
1552
      LM_CRIT("unknown type %d\n", a->type);
1553
*/
1554
0
  }
1555
0
skip:
1556
0
  return ret;
1557
1558
0
error_uri:
1559
0
  LM_ERR("set*: uri too long\n");
1560
0
  if(new_uri)
1561
0
    pkg_free(new_uri);
1562
0
  LM_ERR("run action error at: %s:%d\n", (a->cfile) ? a->cfile : "",
1563
0
      a->cline);
1564
0
  return E_UNSPEC;
1565
0
error_fwd_uri:
1566
  /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
1567
0
error:
1568
0
  LM_ERR("run action error at: %s:%d\n", (a->cfile) ? a->cfile : "",
1569
0
      a->cline);
1570
0
  return ret;
1571
0
}
1572
1573
1574
/* returns: 0, or 1 on success, <0 on error */
1575
/* (0 if drop or break encountered, 1 if not ) */
1576
int run_actions(struct run_act_ctx *h, struct action *a, struct sip_msg *msg)
1577
0
{
1578
0
  struct action *t;
1579
0
  int ret;
1580
0
  struct timeval tvb = {0}, tve = {0};
1581
0
  struct timezone tz;
1582
0
  unsigned int tdiff;
1583
1584
0
  ret = E_UNSPEC;
1585
0
  h->rec_lev++;
1586
0
  if(unlikely(h->rec_lev > max_recursive_level)) {
1587
0
    LM_ERR("too many recursive routing table lookups (%d) giving up!\n",
1588
0
        h->rec_lev);
1589
0
    ret = E_UNSPEC;
1590
0
    goto error;
1591
0
  }
1592
0
  if(unlikely(h->rec_lev == 1)) {
1593
0
    h->run_flags = 0;
1594
0
    h->last_retcode = 0;
1595
0
    _last_returned_code = h->last_retcode;
1596
0
#ifdef USE_LONGJMP
1597
0
    if(unlikely(setjmp(h->jmp_env))) {
1598
0
      h->rec_lev = 0;
1599
0
      ret = h->last_retcode;
1600
0
      goto end;
1601
0
    }
1602
0
#endif
1603
0
  }
1604
1605
0
  if(unlikely(a == 0)) {
1606
0
    LM_DBG("null action list (rec_level=%d)\n", h->rec_lev);
1607
0
    ret = 1;
1608
0
  }
1609
1610
0
  for(t = a; t != 0; t = t->next) {
1611
1612
0
    if(unlikely(cfg_get(core, core_cfg, latency_limit_action) > 0)
1613
0
        && is_printable(cfg_get(core, core_cfg, latency_log))) {
1614
0
      gettimeofday(&tvb, &tz);
1615
0
    }
1616
0
    _cfg_crt_action = t;
1617
0
    if(unlikely(log_prefix_mode == 1)) {
1618
0
      log_prefix_set(msg);
1619
0
    }
1620
0
    ret = do_action(h, t, msg);
1621
0
    _cfg_crt_action = 0;
1622
0
    if(unlikely(log_prefix_mode == 1)) {
1623
0
      log_prefix_set(msg);
1624
0
    }
1625
0
    if(unlikely(cfg_get(core, core_cfg, latency_limit_action) > 0)
1626
0
        && is_printable(cfg_get(core, core_cfg, latency_log))) {
1627
0
      gettimeofday(&tve, &tz);
1628
0
      tdiff = (tve.tv_sec - tvb.tv_sec) * 1000000
1629
0
          + (tve.tv_usec - tvb.tv_usec);
1630
0
      if(tdiff >= cfg_get(core, core_cfg, latency_limit_action)) {
1631
0
        LOG(cfg_get(core, core_cfg, latency_log),
1632
0
            "alert - action [%s (%d)]"
1633
0
            " cfg [%s:%d] took too long [%u us]\n",
1634
0
            is_mod_func(t)
1635
0
                ? ((cmd_export_t *)(t->val[0].u.data))->name
1636
0
                : "corefunc",
1637
0
            t->type, (t->cfile) ? t->cfile : "", t->cline, tdiff);
1638
0
      }
1639
0
    }
1640
    /* break, return or drop/exit stop execution of the current
1641
       block */
1642
0
    if(unlikely(h->run_flags & (BREAK_R_F | RETURN_R_F | EXIT_R_F))) {
1643
0
      if(unlikely(h->run_flags & EXIT_R_F)) {
1644
0
        h->last_retcode = ret;
1645
0
        _last_returned_code = h->last_retcode;
1646
0
#ifdef USE_LONGJMP
1647
0
        longjmp(h->jmp_env, ret);
1648
0
#endif
1649
0
      }
1650
0
      break;
1651
0
    }
1652
    /* ignore error returns */
1653
0
  }
1654
1655
0
  h->rec_lev--;
1656
0
end:
1657
0
  return ret;
1658
1659
1660
0
error:
1661
0
  h->rec_lev--;
1662
0
  return ret;
1663
0
}
1664
1665
1666
#ifdef USE_LONGJMP
1667
/** safe version of run_actions().
1668
 * It always return (it doesn't longjmp on forced script end).
1669
 * @returns 0, or 1 on success, <0 on error
1670
 * (0 if drop or break encountered, 1 if not ) */
1671
int run_actions_safe(
1672
    struct run_act_ctx *h, struct action *a, struct sip_msg *msg)
1673
0
{
1674
0
  struct run_act_ctx ctx;
1675
0
  int ret;
1676
0
  int ign_on_break;
1677
1678
  /* start with a fresh action context */
1679
0
  init_run_actions_ctx(&ctx);
1680
0
  ctx.last_retcode = h->last_retcode;
1681
0
  ign_on_break = h->run_flags & IGNORE_ON_BREAK_R_F;
1682
0
  ctx.run_flags = h->run_flags | IGNORE_ON_BREAK_R_F;
1683
0
  ret = run_actions(&ctx, a, msg);
1684
0
  h->last_retcode = ctx.last_retcode;
1685
0
  h->run_flags = (ctx.run_flags & ~IGNORE_ON_BREAK_R_F) | ign_on_break;
1686
0
  return ret;
1687
0
}
1688
#endif /* USE_LONGJMP */
1689
1690
1691
int run_top_route(struct action *a, sip_msg_t *msg, struct run_act_ctx *c)
1692
0
{
1693
0
  struct run_act_ctx ctx;
1694
0
  struct run_act_ctx *p;
1695
0
  int ret;
1696
0
  flag_t sfbk;
1697
1698
0
  p = (c) ? c : &ctx;
1699
0
  sfbk = getsflags();
1700
0
  setsflagsval(0);
1701
0
  reset_static_buffer();
1702
0
  init_run_actions_ctx(p);
1703
0
  ret = run_actions(p, a, msg);
1704
0
  setsflagsval(sfbk);
1705
0
  return ret;
1706
0
}
1707
1708
1709
/**
1710
 *
1711
 */
1712
int run_child_one_init_route(void)
1713
0
{
1714
0
  struct sip_msg *fmsg;
1715
0
  run_act_ctx_t ctx;
1716
0
  run_act_ctx_t *bctx;
1717
0
  int rtb, rt;
1718
0
  sr_kemi_eng_t *keng = NULL;
1719
0
  str evname = str_init("core:worker-one-init");
1720
1721
0
  LM_DBG("attempting to run event_route[%s]\n", evname.s);
1722
1723
0
  if(kemi_event_route_callback.s != NULL
1724
0
      && kemi_event_route_callback.len > 0) {
1725
0
    keng = sr_kemi_eng_get();
1726
0
    rt = -1;
1727
0
  } else {
1728
0
    rt = route_get(&event_rt, evname.s);
1729
0
  }
1730
0
  if((keng != NULL) || (rt >= 0 && event_rt.rlist[rt] != NULL)) {
1731
0
    if(cfg_child_init()) {
1732
0
      return -1;
1733
0
    }
1734
0
    LM_DBG("executing event_route[%s] (%d)\n", evname.s, rt);
1735
0
    if(faked_msg_init() < 0)
1736
0
      return -1;
1737
0
    fmsg = faked_msg_next();
1738
0
    rtb = get_route_type();
1739
0
    set_route_type(REQUEST_ROUTE);
1740
0
    init_run_actions_ctx(&ctx);
1741
0
    if(keng == NULL) {
1742
0
      run_top_route(event_rt.rlist[rt], fmsg, &ctx);
1743
0
    } else {
1744
0
      bctx = sr_kemi_act_ctx_get();
1745
0
      sr_kemi_act_ctx_set(&ctx);
1746
0
      if(sr_kemi_route(keng, fmsg, EVENT_ROUTE,
1747
0
             &kemi_event_route_callback, &evname)
1748
0
          < 0) {
1749
0
        LM_ERR("error running event route kemi callback\n");
1750
0
        return -1;
1751
0
      }
1752
0
      sr_kemi_act_ctx_set(bctx);
1753
0
    }
1754
0
    if(ctx.run_flags & DROP_R_F) {
1755
0
      LM_ERR("exit due to 'drop' in event route\n");
1756
0
      return -1;
1757
0
    }
1758
0
    set_route_type(rtb);
1759
0
  }
1760
1761
0
  return 0;
1762
0
}