Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/lvalue.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008 iptelorg GmbH
3
 *
4
 * Permission to use, copy, modify, and distribute this software for any
5
 * purpose with or without fee is hereby granted, provided that the above
6
 * copyright notice and this permission notice appear in all copies.
7
 *
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
 */
16
17
/**
18
 * @file
19
 * @brief Kamailio core :: lvalues (assignment)
20
 * \ingroup core
21
 * Module: \ref core
22
 */
23
24
#include "lvalue.h"
25
#include "dprint.h"
26
#include "route.h"
27
28
static char _lval_empty_buf[2] = {0};
29
static str _lval_empty = {_lval_empty_buf, 0};
30
31
/* callback to log assign actions */
32
static log_assign_action_f _log_assign_action = NULL;
33
34
/**
35
 * @brief set callback function log assign actions
36
 */
37
void set_log_assign_action_cb(log_assign_action_f f)
38
0
{
39
0
  _log_assign_action = f;
40
0
}
41
42
/**
43
 * @brief eval rve and assign the result to an avp
44
 *
45
 * eval rve and assign the result to an avp, lv->lv.avp=eval(rve)
46
 * based on do_action() ASSIGN_T.
47
 * @param h  - script context
48
 * @param msg - sip msg
49
 * @param lv - lvalue
50
 * @param rv - rvalue expression
51
 * @return >= 0 on success (expr. bool value), -1 on error
52
 */
53
inline static int lval_avp_assign(struct run_act_ctx *h, struct sip_msg *msg,
54
    struct lvalue *lv, struct rvalue *rv)
55
0
{
56
0
  avp_spec_t *avp;
57
0
  avp_t *r_avp;
58
0
  avp_t *avp_mark;
59
0
  pv_value_t pval;
60
0
  int_str value;
61
0
  unsigned short flags;
62
0
  struct search_state st;
63
0
  int ret, v, destroy_pval;
64
0
  int avp_add;
65
66
#if 0
67
#define AVP_ASSIGN_NOVAL()                                       \
68
  /* unknown value => reset the avp in function of its type */ \
69
  flags = avp->type;                                           \
70
  if(flags & AVP_VAL_STR) {                                    \
71
    value.s.s = "";                                          \
72
    value.s.len = 0;                                         \
73
  } else {                                                     \
74
    value.n = 0;                                             \
75
  }
76
#endif
77
0
#define AVP_ASSIGN_NOVAL()       \
78
  /* no value => delete avp */ \
79
0
  avp_add = 0
80
81
0
  destroy_pval = 0;
82
0
  flags = 0;
83
0
  avp = &lv->lv.avps;
84
0
  ret = 0;
85
0
  avp_add = 1;
86
87
0
  switch(rv->type) {
88
0
    case RV_NONE:
89
0
      LM_BUG("non-initialized rval / rval expr \n");
90
      /* unknown value => reset the avp in function of its type */
91
0
      flags = avp->type;
92
0
      AVP_ASSIGN_NOVAL();
93
0
      ret = -1;
94
0
      break;
95
0
    case RV_LONG:
96
0
      value.n = rv->v.l;
97
0
      flags = avp->type & ~AVP_VAL_STR;
98
0
      ret = !(!value.n);
99
0
      break;
100
0
    case RV_STR:
101
0
      value.s = rv->v.s;
102
0
      flags = avp->type | AVP_VAL_STR;
103
0
      ret = (value.s.len > 0);
104
0
      break;
105
0
    case RV_ACTION_ST:
106
0
      flags = avp->type & ~AVP_VAL_STR;
107
0
      if(rv->v.action) {
108
0
        value.n = run_actions_safe(h, rv->v.action, msg);
109
        /* catch return & break in expr*/
110
0
        h->run_flags &= ~(RETURN_R_F | BREAK_R_F);
111
0
      } else
112
0
        value.n = -1;
113
0
      ret = value.n;
114
0
      break;
115
0
    case RV_BEXPR: /* logic/boolean expr. */
116
0
      value.n = eval_expr(h, rv->v.bexpr, msg);
117
0
      if(unlikely(value.n < 0)) {
118
0
        if(value.n == EXPR_DROP) /* hack to quit on drop */
119
0
          goto drop;
120
0
        LM_WARN("error in expression\n");
121
0
        value.n = 0; /* expr. is treated as false */
122
0
      }
123
0
      flags = avp->type & ~AVP_VAL_STR;
124
0
      ret = value.n;
125
0
      break;
126
0
    case RV_SEL:
127
0
      flags = avp->type | AVP_VAL_STR;
128
0
      v = run_select(&value.s, &rv->v.sel, msg);
129
0
      if(unlikely(v != 0)) {
130
0
        value.s = _lval_empty;
131
0
        if(v < 0) {
132
0
          ret = -1;
133
0
          break;
134
0
        } /* v>0 */
135
0
      }
136
0
      ret = (value.s.len > 0);
137
0
      break;
138
0
    case RV_AVP:
139
0
      avp_mark = 0;
140
0
      if(unlikely((rv->v.avps.type & AVP_INDEX_ALL) == AVP_INDEX_ALL)) {
141
        /* special case: add the value to the avp */
142
0
        r_avp = search_first_avp(
143
0
            rv->v.avps.type, rv->v.avps.name, &value, &st);
144
0
        while(r_avp) {
145
          /* We take only the val type  from the source avp
146
           * and reset the class, track flags and name type  */
147
0
          flags = (avp->type & ~(AVP_INDEX_ALL | AVP_VAL_STR))
148
0
              | (r_avp->flags
149
0
                  & ~(AVP_CLASS_ALL | AVP_TRACK_ALL
150
0
                      | AVP_NAME_STR | AVP_NAME_RE));
151
0
          if(add_avp_before(avp_mark, flags, avp->name, value) < 0) {
152
0
            LM_ERR("failed to assign avp\n");
153
0
            ret = -1;
154
0
            goto error;
155
0
          }
156
          /* move the mark, so the next found AVP will come before
157
           * the one currently added so they will have the same
158
           * order as in the source list */
159
0
          if(avp_mark)
160
0
            avp_mark = avp_mark->next;
161
0
          else
162
0
            avp_mark = search_first_avp(flags, avp->name, 0, 0);
163
0
          r_avp = search_next_avp(&st, &value);
164
0
        }
165
0
        ret = 1;
166
0
        goto end;
167
0
      } else {
168
        /* normal case, value is replaced */
169
0
        r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
170
0
            &value, rv->v.avps.index);
171
0
        if(likely(r_avp)) {
172
          /* take only the val type from the source avp
173
           * and reset the class, track flags and name type  */
174
0
          flags = (avp->type & ~AVP_VAL_STR)
175
0
              | (r_avp->flags
176
0
                  & ~(AVP_CLASS_ALL | AVP_TRACK_ALL
177
0
                      | AVP_NAME_STR | AVP_NAME_RE));
178
0
          ret = 1;
179
0
        } else {
180
          /* on error, keep the type of the assigned avp, but
181
           * reset it to an empty value */
182
0
          AVP_ASSIGN_NOVAL();
183
0
          ret = 0;
184
0
          break;
185
0
        }
186
0
      }
187
0
      break;
188
0
    case RV_PVAR:
189
0
      memset(&pval, 0, sizeof(pval));
190
0
      if(likely(pv_get_spec_value(msg, &rv->v.pvs, &pval) == 0)) {
191
0
        destroy_pval = 1;
192
0
        if(pval.flags & PV_TYPE_INT) {
193
0
          value.n = pval.ri;
194
0
          ret = value.n;
195
0
          flags = avp->type & ~AVP_VAL_STR;
196
0
        } else if(pval.flags & PV_VAL_STR) {
197
0
          value.s = pval.rs;
198
0
          ret = (value.s.len > 0);
199
0
          flags = avp->type | AVP_VAL_STR;
200
0
        } else if(pval.flags == PV_VAL_NONE
201
0
              || (pval.flags & (PV_VAL_NULL | PV_VAL_EMPTY))) {
202
0
          AVP_ASSIGN_NOVAL();
203
0
          ret = 0;
204
0
        }
205
0
      } else {
206
        /* non existing pvar */
207
        /* on error, keep the type of the assigned avp, but
208
         * reset it to an empty value */
209
0
        AVP_ASSIGN_NOVAL();
210
0
        ret = 0;
211
0
      }
212
0
      break;
213
0
  }
214
  /* If the left attr was specified without indexing brackets delete
215
   * existing AVPs before adding the new value */
216
0
  delete_avp(avp->type, avp->name);
217
0
  if(avp_add && (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0)) {
218
0
    LM_ERR("failed to assign value to avp\n");
219
0
    goto error;
220
0
  }
221
0
end:
222
0
  if(destroy_pval)
223
0
    pv_value_destroy(&pval);
224
0
  return ret;
225
0
error:
226
0
  if(destroy_pval)
227
0
    pv_value_destroy(&pval);
228
0
  return -1;
229
0
drop:
230
0
  if(destroy_pval)
231
0
    pv_value_destroy(&pval);
232
0
  return EXPR_DROP;
233
0
}
234
235
236
/**
237
 * @brief eval rve and assign the result to a pvar
238
 *
239
 * eval rve and assign the result to a pvar, lv->lv.pvar=eval(rve)
240
 * based on do_action() ASSIGN_T.
241
 * @param h  - script context
242
 * @param msg - sip msg
243
 * @param lv - lvalue
244
 * @param rv - rvalue expression
245
 * @return >= 0 on success (expr. bool value), -1 on error
246
 */
247
inline static int lval_pvar_assign(struct run_act_ctx *h, struct sip_msg *msg,
248
    struct lvalue *lv, struct rvalue *rv)
249
0
{
250
0
  pv_spec_t *pvar;
251
0
  pv_value_t pval;
252
0
  avp_t *r_avp;
253
0
  int_str avp_val;
254
0
  int ret;
255
0
  int v;
256
0
  int destroy_pval;
257
258
0
#define PVAR_ASSIGN_NOVAL()            \
259
  /* no value found => "undefine" */ \
260
0
  pv_get_null(msg, 0, &pval)
261
262
0
  destroy_pval = 0;
263
0
  pvar = lv->lv.pvs;
264
0
  if(unlikely(!pv_is_w(pvar))) {
265
0
    LM_ERR("read only pvar\n");
266
0
    goto error;
267
0
  }
268
0
  memset(&pval, 0, sizeof(pval));
269
0
  ret = 0;
270
0
  switch(rv->type) {
271
0
    case RV_NONE:
272
0
      LM_BUG("non-initialized rval / rval expr \n");
273
0
      PVAR_ASSIGN_NOVAL();
274
0
      ret = -1;
275
0
      break;
276
0
    case RV_LONG:
277
0
      pval.flags = PV_TYPE_INT | PV_VAL_INT;
278
0
      pval.ri = rv->v.l;
279
0
      ret = !(!pval.ri);
280
0
      break;
281
0
    case RV_STR:
282
0
      pval.flags = PV_VAL_STR;
283
0
      pval.rs = rv->v.s;
284
0
      ret = (pval.rs.len > 0);
285
0
      break;
286
0
    case RV_ACTION_ST:
287
0
      pval.flags = PV_TYPE_INT | PV_VAL_INT;
288
0
      if(rv->v.action) {
289
0
        pval.ri = run_actions_safe(h, rv->v.action, msg);
290
        /* catch return & break in expr*/
291
0
        h->run_flags &= ~(RETURN_R_F | BREAK_R_F);
292
0
      } else
293
0
        pval.ri = 0;
294
0
      ret = !(!pval.ri);
295
0
      break;
296
0
    case RV_BEXPR: /* logic/boolean expr. */
297
0
      pval.flags = PV_TYPE_INT | PV_VAL_INT;
298
0
      pval.ri = eval_expr(h, rv->v.bexpr, msg);
299
0
      if(unlikely(pval.ri < 0)) {
300
0
        if(pval.ri == EXPR_DROP) /* hack to quit on drop */
301
0
          goto drop;
302
0
        LM_WARN("error in expression\n");
303
0
        pval.ri = 0; /* expr. is treated as false */
304
0
      }
305
0
      ret = !(!pval.ri);
306
0
      break;
307
0
    case RV_SEL:
308
0
      pval.flags = PV_VAL_STR;
309
0
      v = run_select(&pval.rs, &rv->v.sel, msg);
310
0
      if(unlikely(v != 0)) {
311
0
        pval.flags |= PV_VAL_EMPTY;
312
0
        pval.rs = _lval_empty;
313
0
        if(v < 0) {
314
0
          ret = -1;
315
0
          break;
316
0
        }
317
0
      }
318
0
      ret = (pval.rs.len > 0);
319
0
      break;
320
0
    case RV_AVP:
321
0
      r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
322
0
          &avp_val, rv->v.avps.index);
323
0
      if(likely(r_avp)) {
324
0
        if(r_avp->flags & AVP_VAL_STR) {
325
0
          pval.flags = PV_VAL_STR;
326
0
          pval.rs = avp_val.s;
327
0
          ret = (pval.rs.len > 0);
328
0
        } else {
329
0
          pval.flags = PV_TYPE_INT | PV_VAL_INT;
330
0
          pval.ri = avp_val.n;
331
0
          ret = !(!pval.ri);
332
0
        }
333
0
      } else {
334
0
        PVAR_ASSIGN_NOVAL();
335
0
        ret = 0; /* avp not defined (valid case) */
336
0
        break;
337
0
      }
338
0
      break;
339
0
    case RV_PVAR:
340
0
      if(likely(pv_get_spec_value(msg, &rv->v.pvs, &pval) == 0)) {
341
0
        destroy_pval = 1;
342
0
        if(pval.flags & PV_TYPE_INT) {
343
0
          ret = !(!pval.ri);
344
0
        } else if(pval.flags & PV_VAL_STR) {
345
0
          ret = (pval.rs.len > 0);
346
0
        } else {
347
          /* no value / not defined (e.g. avp) -> keep the flags */
348
0
          ret = 0;
349
0
        }
350
0
      } else {
351
0
        LM_ERR("non existing right pvar\n");
352
0
        PVAR_ASSIGN_NOVAL();
353
0
        ret = -1;
354
0
      }
355
0
      break;
356
0
  }
357
0
  if(unlikely(pvar->setf(msg, &pvar->pvp, EQ_T, &pval) < 0)) {
358
0
    LM_ERR("setting pvar failed\n");
359
0
    goto error;
360
0
  }
361
0
  if(destroy_pval)
362
0
    pv_value_destroy(&pval);
363
0
  return ret;
364
0
error:
365
0
  if(destroy_pval)
366
0
    pv_value_destroy(&pval);
367
0
  return -1;
368
0
drop:
369
0
  if(destroy_pval)
370
0
    pv_value_destroy(&pval);
371
0
  return EXPR_DROP;
372
0
}
373
374
375
/** eval rve and assign the result to lv
376
 * lv=eval(rve)
377
 *
378
 * @param h  - script context
379
 * @param msg - sip msg
380
 * @param lv - lvalue
381
 * @param rve - rvalue expression
382
 * @return >= 0 on success (expr. bool value), -1 on error
383
 */
384
int lval_assign(struct run_act_ctx *h, struct sip_msg *msg, struct lvalue *lv,
385
    struct rval_expr *rve)
386
0
{
387
0
  struct rvalue *rv;
388
0
  int ret;
389
390
0
  ret = -1;
391
0
  rv = rval_expr_eval(h, msg, rve);
392
0
  if(unlikely(rv == 0)) {
393
0
    LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
394
0
        rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line,
395
0
        rve->fpos.e_col);
396
0
    goto error;
397
0
  }
398
0
  switch(lv->type) {
399
0
    case LV_NONE:
400
0
      LM_BUG("uninitialized/invalid lvalue (%d) (cfg line: %d)\n",
401
0
          lv->type, rve->fpos.s_line);
402
0
      goto error;
403
0
    case LV_AVP:
404
0
      ret = lval_avp_assign(h, msg, lv, rv);
405
0
      break;
406
0
    case LV_PVAR:
407
0
      ret = lval_pvar_assign(h, msg, lv, rv);
408
0
      break;
409
0
  }
410
0
  if(unlikely(ret < 0)) {
411
0
    LM_ERR("assignment failed at pos: (%d,%d-%d,%d)\n", rve->fpos.s_line,
412
0
        rve->fpos.s_col, rve->fpos.e_line, rve->fpos.e_col);
413
0
  } else {
414
0
    if(unlikely(_log_assign_action != NULL))
415
0
      _log_assign_action(msg, lv);
416
0
  }
417
0
  rval_destroy(rv);
418
0
  return ret;
419
0
error:
420
0
  if(rv)
421
0
    rval_destroy(rv);
422
0
  return ret;
423
0
}