Coverage Report

Created: 2023-11-19 07:01

/src/kamailio/src/core/ppcfg.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
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 :: ppcfg.c - config preprocessor directives
20
 * \ingroup core
21
 * Module: \ref core
22
 */
23
24
#include <stdio.h>
25
#include <string.h>
26
#include <sys/types.h>
27
#include <unistd.h>
28
29
#include "mem/mem.h"
30
#include "ut.h"
31
#include "trim.h"
32
#include "re.h"
33
#include "pvar.h"
34
#include "pvapi.h"
35
#include "str_list.h"
36
#include "dprint.h"
37
#include "utils/snexpr.h"
38
39
#include "ppcfg.h"
40
#include "fmsg.h"
41
42
typedef struct _pp_subst_rule
43
{
44
  char *indata;
45
  void *ppdata;
46
  struct _pp_subst_rule *next;
47
} pp_subst_rule_t;
48
49
static pp_subst_rule_t *pp_subst_rules_head = NULL;
50
static pp_subst_rule_t *pp_subst_rules_tail = NULL;
51
static int _pp_ifdef_level = 0;
52
static str_list_t *_ksr_substdef_strlist = NULL;
53
54
int pp_def_qvalue(str *defval, str *outval)
55
0
{
56
0
  str newval;
57
0
  str_list_t *sb;
58
59
0
  if(pv_get_buffer_size() < defval->len + 4) {
60
0
    LM_ERR("defined value is too large %d < %d\n", pv_get_buffer_size(),
61
0
        defval->len + 4);
62
0
    return -1;
63
0
  }
64
0
  newval.s = pv_get_buffer();
65
0
  newval.s[0] = '"';
66
0
  memcpy(newval.s + 1, defval->s, defval->len);
67
0
  newval.s[defval->len + 1] = '"';
68
0
  newval.s[defval->len + 2] = '\0';
69
0
  newval.len = defval->len + 2;
70
0
  sb = str_list_block_add(&_ksr_substdef_strlist, newval.s, newval.len);
71
0
  if(sb == NULL) {
72
0
    LM_ERR("failed to link quoted value [%.*s]\n", defval->len, defval->s);
73
0
    return -1;
74
0
  }
75
0
  *outval = sb->s;
76
77
0
  return 0;
78
0
}
79
80
int pp_subst_add(char *data)
81
0
{
82
0
  struct subst_expr *se;
83
0
  str subst;
84
0
  pp_subst_rule_t *pr;
85
86
0
  subst.s = data;
87
0
  subst.len = strlen(subst.s);
88
  /* check for early invalid rule */
89
0
  if(subst.len <= 0)
90
0
    return -1;
91
0
  pr = (pp_subst_rule_t *)pkg_malloc(sizeof(pp_subst_rule_t));
92
0
  if(pr == NULL) {
93
0
    PKG_MEM_ERROR;
94
0
    return -1;
95
0
  }
96
0
  memset(pr, 0, sizeof(pp_subst_rule_t));
97
98
0
  se = subst_parser(&subst);
99
0
  if(se == 0) {
100
0
    LM_ERR("bad subst expression: %s\n", data);
101
0
    pkg_free(pr);
102
0
    return -2;
103
0
  }
104
0
  pr->indata = data;
105
0
  pr->ppdata = (void *)se;
106
0
  if(pp_subst_rules_head == NULL) {
107
0
    pp_subst_rules_head = pr;
108
0
  } else {
109
0
    pp_subst_rules_tail->next = pr;
110
0
  }
111
0
  pp_subst_rules_tail = pr;
112
113
0
  LM_DBG("### added subst expression: [%s]\n", data);
114
115
0
  return 0;
116
0
}
117
118
int pp_substdef_add(char *data, int mode)
119
0
{
120
0
  char c;
121
0
  char *p;
122
0
  str defname;
123
0
  str defvalue;
124
0
  str newval;
125
0
  sip_msg_t *fmsg;
126
0
  str_list_t *sb;
127
128
0
  if(pp_subst_add(data) < 0) {
129
0
    LM_ERR("subst rule cannot be added\n");
130
0
    goto error;
131
0
  }
132
133
0
  p = data;
134
0
  c = *p;
135
0
  if(c == '\\') {
136
0
    LM_ERR("invalid separator char [%c] in [%s]\n", c, data);
137
0
    goto error;
138
0
  }
139
0
  p++;
140
  /* find regexp */
141
0
  defname.s = p;
142
0
  for(; *p; p++) {
143
    /* if unescaped sep. char */
144
0
    if((*p == c) && (*(p - 1) != '\\'))
145
0
      goto found_regexp;
146
0
  }
147
0
  LM_ERR("separator [%c] not found after regexp: [%s]\n", c, data);
148
0
  goto error;
149
150
0
found_regexp:
151
0
  defname.len = p - defname.s;
152
0
  if(defname.len == 0) {
153
0
    LM_ERR("define name too short\n");
154
0
    goto error;
155
0
  }
156
157
0
  p++;
158
0
  defvalue.s = p;
159
  /* find replacement */
160
0
  for(; *p; p++) {
161
    /* if unescaped sep. char */
162
0
    if((*p == c) && (*(p - 1) != '\\'))
163
0
      goto found_repl;
164
0
  }
165
0
  LM_ERR("separator [%c] not found after replacement: [%s]\n", c, data);
166
0
  goto error;
167
168
0
found_repl:
169
0
  defvalue.len = p - defvalue.s;
170
171
0
  pp_define_set_type(KSR_PPDEF_DEFINE);
172
0
  if(pp_define(defname.len, defname.s) < 0) {
173
0
    LM_ERR("cannot set define name\n");
174
0
    goto error;
175
0
  }
176
0
  if(memchr(defvalue.s, '$', defvalue.len) != NULL) {
177
0
    fmsg = faked_msg_get_next();
178
0
    if(pv_eval_str(fmsg, &newval, &defvalue) >= 0) {
179
0
      if(mode != KSR_PPDEF_QUOTED) {
180
0
        sb = str_list_block_add(
181
0
            &_ksr_substdef_strlist, newval.s, newval.len);
182
0
        if(sb == NULL) {
183
0
          LM_ERR("failed to handle substdef: [%s]\n", data);
184
0
          return -1;
185
0
        }
186
0
        defvalue = sb->s;
187
0
      } else {
188
0
        defvalue = newval;
189
0
      }
190
0
    }
191
0
  }
192
0
  if(mode == KSR_PPDEF_QUOTED) {
193
0
    if(pp_def_qvalue(&defvalue, &newval) < 0) {
194
0
      LM_ERR("failed to enclose in quotes the value\n");
195
0
      return -1;
196
0
    }
197
0
    defvalue = newval;
198
0
  }
199
0
  if(pp_define_set(defvalue.len, defvalue.s, KSR_PPDEF_QUOTED) < 0) {
200
0
    LM_ERR("cannot set define value\n");
201
0
    goto error;
202
0
  }
203
204
0
  LM_DBG("### added substdef: [%.*s]=[%.*s] (%d)\n", defname.len, defname.s,
205
0
      defvalue.len, defvalue.s, mode);
206
207
0
  return 0;
208
209
0
error:
210
0
  return -1;
211
0
}
212
213
int pp_subst_run(char **data)
214
0
{
215
0
  str *result;
216
0
  pp_subst_rule_t *pr;
217
0
  int i;
218
219
0
  if(pp_subst_rules_head == NULL)
220
0
    return 0;
221
0
  if(data == NULL || *data == NULL)
222
0
    return 0;
223
224
0
  if(strlen(*data) == 0)
225
0
    return 0;
226
0
  pr = pp_subst_rules_head;
227
228
0
  i = 0;
229
0
  while(pr) {
230
0
    sip_msg_t *fmsg = faked_msg_get_next();
231
0
    result = subst_str(*data, fmsg, (struct subst_expr *)pr->ppdata,
232
0
        0); /* pkg malloc'ed result */
233
0
    if(result != NULL) {
234
0
      i++;
235
0
      LM_DBG("preprocess subst applied [#%d] to [%s]"
236
0
           " - returning new string [%s]\n",
237
0
          i, *data, result->s);
238
0
      pkg_free(*data);
239
0
      *data = result->s;
240
0
      pkg_free(result);
241
0
    }
242
0
    pr = pr->next;
243
0
  }
244
245
0
  if(i != 0)
246
0
    return 1;
247
0
  return 0;
248
0
}
249
250
/**
251
 *
252
 */
253
void pp_ifdef_level_update(int val)
254
0
{
255
0
  _pp_ifdef_level += val;
256
0
}
257
258
/**
259
 *
260
 */
261
int pp_ifdef_level_check(void)
262
0
{
263
0
  if(_pp_ifdef_level != 0) {
264
0
    return -1;
265
0
  } else {
266
0
    LM_DBG("same number of pairing preprocessor directives"
267
0
         " #!IF[N]DEF - #!ENDIF\n");
268
0
  }
269
0
  return 0;
270
0
}
271
272
void pp_ifdef_level_error(void)
273
0
{
274
0
  if(_pp_ifdef_level != 0) {
275
0
    if(_pp_ifdef_level > 0) {
276
0
      LM_ERR("different number of preprocessor directives:"
277
0
           " %d more #!if[n]def as #!endif\n",
278
0
          _pp_ifdef_level);
279
0
    } else {
280
0
      LM_ERR("different number of preprocessor directives:"
281
0
           " %d more #!endif as #!if[n]def\n",
282
0
          (_pp_ifdef_level) * -1);
283
0
    }
284
0
  }
285
0
}
286
287
/**
288
 *
289
 */
290
void pp_define_core(void)
291
0
{
292
0
  char defval[64];
293
0
  char *p;
294
0
  int n;
295
0
  str_list_t *sb;
296
297
0
  strcpy(defval, NAME);
298
0
  p = defval;
299
0
  while(*p) {
300
0
    *p = (char)toupper(*p);
301
0
    p++;
302
0
  }
303
304
0
  n = snprintf(p, 64 - (int)(p - defval), "_%u", VERSIONVAL / 1000000);
305
0
  if(n < 0 || n >= 64 - (int)(p - defval)) {
306
0
    LM_ERR("failed to build define token\n");
307
0
    return;
308
0
  }
309
0
  pp_define_set_type(KSR_PPDEF_DEFINE);
310
0
  if(pp_define(strlen(defval), defval) < 0) {
311
0
    LM_ERR("unable to set cfg define: %s\n", defval);
312
0
    return;
313
0
  }
314
315
0
  n = snprintf(p, 64 - (int)(p - defval), "_%u_%u", VERSIONVAL / 1000000,
316
0
      (VERSIONVAL % 1000000) / 1000);
317
0
  if(n < 0 || n >= 64 - (int)(p - defval)) {
318
0
    LM_ERR("failed to build define token\n");
319
0
    return;
320
0
  }
321
0
  pp_define_set_type(KSR_PPDEF_DEFINE);
322
0
  if(pp_define(strlen(defval), defval) < 0) {
323
0
    LM_ERR("unable to set cfg define: %s\n", defval);
324
0
    return;
325
0
  }
326
327
0
  n = snprintf(p, 64 - (int)(p - defval), "_%u_%u_%u", VERSIONVAL / 1000000,
328
0
      (VERSIONVAL % 1000000) / 1000, VERSIONVAL % 1000);
329
0
  if(n < 0 || n >= 64 - (int)(p - defval)) {
330
0
    LM_ERR("failed to build define token\n");
331
0
    return;
332
0
  }
333
0
  pp_define_set_type(KSR_PPDEF_DEFINE);
334
0
  if(pp_define(strlen(defval), defval) < 0) {
335
0
    LM_ERR("unable to set cfg define: %s\n", defval);
336
0
    return;
337
0
  }
338
339
0
  strcpy(p, "_VERSION");
340
0
  pp_define_set_type(KSR_PPDEF_DEFINE);
341
0
  if(pp_define(strlen(defval), defval) < 0) {
342
0
    LM_ERR("unable to set cfg define: %s\n", defval);
343
0
    return;
344
0
  }
345
346
0
  n = snprintf(defval, 64, "%u", VERSIONVAL);
347
0
  if(n < 0 || n >= 64) {
348
0
    LM_ERR("failed to build version define value\n");
349
0
    return;
350
0
  }
351
0
  sb = str_list_block_add(&_ksr_substdef_strlist, defval, strlen(defval));
352
0
  if(sb == NULL) {
353
0
    LM_ERR("failed to store version define value\n");
354
0
    return;
355
0
  }
356
0
  if(pp_define_set(sb->s.len, sb->s.s, KSR_PPDEF_NORMAL) < 0) {
357
0
    LM_ERR("error setting version define value\n");
358
0
    return;
359
0
  }
360
361
0
  if(pp_define(strlen("OS_NAME"), "OS_NAME") < 0) {
362
0
    LM_ERR("unable to set cfg define OS_NAME\n");
363
0
    return;
364
0
  }
365
0
  if(pp_define_set(strlen(OS_QUOTED), OS_QUOTED, KSR_PPDEF_NORMAL) < 0) {
366
0
    LM_ERR("error setting OS_NAME define value\n");
367
0
    return;
368
0
  }
369
0
}
370
371
static struct snexpr *pp_snexpr_defval(char *vname)
372
0
{
373
0
  int idx = 0;
374
0
  ksr_ppdefine_t *pd = NULL;
375
376
0
  if(vname == NULL) {
377
0
    return NULL;
378
0
  }
379
380
0
  idx = pp_lookup(strlen(vname), vname);
381
0
  if(idx < 0) {
382
0
    LM_DBG("define id [%s] not found - return 0\n", vname);
383
0
    return snexpr_convert_num(0, SNE_OP_CONSTNUM);
384
0
  }
385
0
  pd = pp_get_define(idx);
386
0
  if(pd == NULL) {
387
0
    LM_DBG("define id [%s] at index [%d] not found - return 0\n", vname,
388
0
        idx);
389
0
    return snexpr_convert_num(0, SNE_OP_CONSTNUM);
390
0
  }
391
392
0
  if(pd->value.s != NULL) {
393
0
    LM_DBG("define id [%s] at index [%d] found with value - return "
394
0
         "[%.*s]\n",
395
0
        vname, idx, pd->value.len, pd->value.s);
396
0
    if(pd->value.len >= 2
397
0
        && (pd->value.s[0] == '"' || pd->value.s[0] == '\'')
398
0
        && pd->value.s[0] == pd->value.s[pd->value.len - 1]) {
399
      /* strip enclosing quotes for string value */
400
0
      return snexpr_convert_stzl(
401
0
          pd->value.s + 1, pd->value.len - 2, SNE_OP_CONSTSTZ);
402
0
    } else {
403
0
      return snexpr_convert_stzl(
404
0
          pd->value.s, pd->value.len, SNE_OP_CONSTSTZ);
405
0
    }
406
0
  } else {
407
0
    LM_DBG("define id [%s] at index [%d] found without value - return 1\n",
408
0
        vname, idx);
409
0
    return snexpr_convert_num(1, SNE_OP_CONSTNUM);
410
0
  }
411
0
}
412
413
void pp_ifexp_eval(char *exval, int exlen)
414
0
{
415
0
  str exstr;
416
0
  struct snexpr_var_list vars = {0};
417
0
  struct snexpr *e = NULL;
418
0
  struct snexpr *result = NULL;
419
0
  int b = 0;
420
421
0
  exstr.s = exval;
422
0
  exstr.len = exlen;
423
0
  trim(&exstr);
424
425
0
  LM_DBG("evaluating [%.*s]\n", exstr.len, exstr.s);
426
427
0
  e = snexpr_create(exstr.s, exstr.len, &vars, NULL, pp_snexpr_defval);
428
0
  if(e == NULL) {
429
0
    LM_ERR("failed to create expression [%.*s]\n", exstr.len, exstr.s);
430
0
    pp_ifexp_state(0);
431
0
    return;
432
0
  }
433
434
0
  result = snexpr_eval(e);
435
436
0
  if(result == NULL) {
437
0
    LM_ERR("expression evaluation [%.*s] is null\n", exstr.len, exstr.s);
438
0
    pp_ifexp_state(0);
439
0
    goto end;
440
0
  }
441
442
0
  if(result->type == SNE_OP_CONSTNUM) {
443
0
    LM_DBG("expression number result: %g\n", result->param.num.nval);
444
0
    if(result->param.num.nval) {
445
0
      b = 1;
446
0
    } else {
447
0
      b = 0;
448
0
    }
449
0
  } else if(result->type == SNE_OP_CONSTSTZ) {
450
0
    if(result->param.stz.sval == NULL
451
0
        || strlen(result->param.stz.sval) == 0) {
452
0
      LM_DBG("expression string result: <%s>\n",
453
0
          (result->param.stz.sval) ? "empty" : "null");
454
0
      b = 0;
455
0
    } else {
456
0
      LM_DBG("expression string result: [%s]\n", result->param.stz.sval);
457
0
      b = 1;
458
0
    }
459
0
  }
460
461
0
  LM_DBG("expression evaluation [%.*s] is [%s]\n", exstr.len, exstr.s,
462
0
      (b) ? "true" : "false");
463
464
0
  pp_ifexp_state(b);
465
466
0
  snexpr_result_free(result);
467
0
end:
468
0
  snexpr_destroy(e, &vars);
469
0
}
470
471
char *pp_defexp_eval(char *exval, int exlen, int qmode)
472
0
{
473
0
  str exstr;
474
0
  struct snexpr_var_list vars = {0};
475
0
  struct snexpr *e = NULL;
476
0
  struct snexpr *result = NULL;
477
0
  str sval = STR_NULL;
478
0
  char *res = NULL;
479
480
0
  exstr.s = exval;
481
0
  exstr.len = exlen;
482
0
  trim(&exstr);
483
484
0
  LM_DBG("evaluating [%.*s]\n", exstr.len, exstr.s);
485
486
0
  e = snexpr_create(exstr.s, exstr.len, &vars, NULL, pp_snexpr_defval);
487
0
  if(e == NULL) {
488
0
    LM_ERR("failed to create expression [%.*s]\n", exstr.len, exstr.s);
489
0
    return NULL;
490
0
  }
491
492
0
  result = snexpr_eval(e);
493
494
0
  if(result == NULL) {
495
0
    LM_ERR("expression evaluation [%.*s] is null\n", exstr.len, exstr.s);
496
0
    goto end;
497
0
  }
498
499
0
  if(result->type == SNE_OP_CONSTNUM) {
500
0
    LM_DBG("expression number result: %g\n", result->param.num.nval);
501
0
    sval.s = int2str((long)result->param.num.nval, &sval.len);
502
0
    if(sval.s == NULL) {
503
0
      goto done;
504
0
    }
505
0
  } else if(result->type == SNE_OP_CONSTSTZ) {
506
0
    if(result->param.stz.sval == NULL) {
507
0
      LM_DBG("expression string result is null\n");
508
0
      goto done;
509
0
    }
510
0
    LM_DBG("expression string result: [%s]\n", result->param.stz.sval);
511
0
    sval.s = result->param.stz.sval;
512
0
    sval.len = strlen(result->param.stz.sval);
513
0
  }
514
515
0
  if(qmode == 1) {
516
0
    res = (char *)pkg_malloc(sval.len + 3);
517
0
  } else {
518
0
    res = (char *)pkg_malloc(sval.len + 1);
519
0
  }
520
0
  if(res == NULL) {
521
0
    PKG_MEM_ERROR;
522
0
    goto done;
523
0
  }
524
0
  if(qmode == 1) {
525
0
    res[0] = '"';
526
0
    memcpy(res + 1, sval.s, sval.len);
527
0
    res[sval.len + 1] = '"';
528
0
    res[sval.len + 2] = '\0';
529
0
    LM_DBG("expression quoted string result: [%s]\n", res);
530
0
  } else {
531
0
    memcpy(res, sval.s, sval.len);
532
0
    res[sval.len] = '\0';
533
0
  }
534
535
0
done:
536
0
  snexpr_result_free(result);
537
0
end:
538
0
  snexpr_destroy(e, &vars);
539
0
  return res;
540
0
}
541
542
/* vi: set ts=4 sw=4 tw=79:ai:cindent: */