Coverage Report

Created: 2024-02-28 06:28

/src/opensips/pvar.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Copyright (C) 2010-2020 OpenSIPS Solutions
3
 * Copyright (C) 2005-2009 Voice Sistem SRL
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * History:
23
 * --------
24
 * 2004-10-20 - added header name specifier (ramona)
25
 * 2005-06-14 - added avp name specifier (ramona)
26
 * 2005-06-18 - added color printing support via escape sequesnces
27
 *              contributed by Ingo Flaschberger (daniel)
28
 * 2005-06-22 - created this file from modules/xlog/pv_lib.c (daniel)
29
 * 2009-04-28 - $ct and $ct.fields() PVs added (bogdan)
30
 * 2009-05-02 - $branch() added, $br, $bR, $bf, $bF removed (bogdan)
31
 */
32
33
#include <stdio.h>
34
#include <string.h>
35
#include <time.h>
36
#include <sys/types.h>
37
#include <unistd.h>
38
39
#include "dprint.h"
40
#include "mem/mem.h"
41
#include "mem/shm_mem.h"
42
#include "ut.h"
43
#include "trim.h"
44
#include "dset.h"
45
#include "action.h"
46
#include "socket_info.h"
47
#include "route_struct.h"
48
#include "usr_avp.h"
49
#include "errinfo.h"
50
#include "transformations.h"
51
#include "script_var.h"
52
#include "pvar.h"
53
#include "flags.h"
54
#include "xlog.h"
55
56
#include "parser/parse_from.h"
57
#include "parser/parse_uri.h"
58
#include "parser/parse_hname2.h"
59
#include "parser/parse_content.h"
60
#include "parser/parse_refer_to.h"
61
#include "parser/parse_rpid.h"
62
#include "parser/parse_diversion.h"
63
#include "parser/parse_ppi.h"
64
#include "parser/parse_pai.h"
65
#include "parser/digest/digest.h"
66
#include "parser/contact/parse_contact.h"
67
68
2.87k
#define is_in_str(p, in) (p<in->s+in->len && *p)
69
70
extern int curr_action_line;
71
extern char *curr_action_file;
72
73
typedef struct _pv_extra
74
{
75
  pv_export_t pve;
76
  struct _pv_extra *next;
77
} pv_extra_t, *pv_extra_p;
78
79
pv_extra_p  *_pv_extra_list=0;
80
81
static str str_marker = { PV_MARKER_STR, 1 };
82
83
/* IMPORTANT : the "const" strings returned by the var functions must
84
   be read-write (as they may be changed by the script interpreter), so
85
   we need to allocated as array and not as pointing to RO data segment
86
   */
87
static char _str_null_hlp[] = "<null>";
88
static str str_null         = str_init(_str_null_hlp);
89
90
static char _str_empty_hlp[] = "";
91
static str str_empty         = str_init(_str_empty_hlp);
92
93
int _pv_pid = 0;
94
95
0
#define PV_FIELD_DELIM ", "
96
0
#define PV_FIELD_DELIM_LEN (sizeof(PV_FIELD_DELIM) - 1)
97
98
0
#define PV_LOCAL_BUF_SIZE 511
99
static char pv_local_buf[PV_LOCAL_BUF_SIZE+1];
100
101
/* pv context list */
102
pv_context_t* pv_context_lst = NULL;
103
104
static pv_context_t* pv_get_context(const str* name);
105
static pv_context_t* add_pv_context(const str* name, pv_contextf_t get_context);
106
107
static int pv_parse_argv_name(pv_spec_p sp, const str *in);
108
static int pv_get_argv(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res);
109
static int pv_contextlist_check(void);
110
/* always obtain a printable version of the given (pv_value_t *) */
111
static str pv_value_print(const pv_value_t *val);
112
113
static int pvc_before_check = 1;
114
115
int pv_print_buf_size = 20000;
116
0
#define PV_PRINT_BUF_NO   7
117
str *pv_print_buf;
118
119
0
#define is_pv_print_buf(p) (p >= (char *)pv_print_buf && \
120
0
      p <= (char *)pv_print_buf + \
121
0
        PV_PRINT_BUF_NO * (sizeof(*pv_print_buf) + pv_print_buf_size))
122
123
int init_pvar_support(void)
124
0
{
125
0
  int i;
126
127
  /* check pv context list */
128
0
  if (pv_contextlist_check() != 0) {
129
0
    LM_ERR("used pv context that was not defined\n");
130
0
    return -1;
131
0
  }
132
133
0
  pv_print_buf = pkg_malloc(PV_PRINT_BUF_NO * (sizeof(str)
134
0
                                 + pv_print_buf_size));
135
0
  if (!pv_print_buf) {
136
0
    LM_ERR("oom\n");
137
0
    return -1;
138
0
  }
139
140
0
  for (i = 0; i < PV_PRINT_BUF_NO; i++) {
141
0
    pv_print_buf[i].s = (char *)(pv_print_buf + PV_PRINT_BUF_NO)
142
0
                                  + i * pv_print_buf_size;
143
0
    pv_print_buf[i].len = pv_print_buf_size;
144
0
  }
145
146
0
  return 0;
147
0
}
148
149
/* route param variable */
150
static int pv_get_param(struct sip_msg *msg,  pv_param_t *ip, pv_value_t *res);
151
static int pv_parse_param_name(pv_spec_p sp, const str *in);
152
153
/********** helper functions ********/
154
/**
155
 * convert unsigned int to pv_value_t
156
 */
157
int pv_get_uintval(struct sip_msg *msg, pv_param_t *param,
158
    pv_value_t *res, unsigned int uival)
159
68.1k
{
160
68.1k
  int l = 0;
161
68.1k
  char *ch = NULL;
162
163
68.1k
  if(res==NULL)
164
0
    return -1;
165
166
68.1k
  ch = int2str(uival, &l);
167
68.1k
  res->rs.s = ch;
168
68.1k
  res->rs.len = l;
169
170
68.1k
  res->ri = (int)uival;
171
68.1k
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
172
68.1k
  return 0;
173
68.1k
}
174
175
/**
176
 * convert signed int to pv_value_t
177
 */
178
int pv_get_sintval(struct sip_msg *msg, pv_param_t *param,
179
    pv_value_t *res, int sival)
180
75.4k
{
181
75.4k
  int l = 0;
182
75.4k
  char *ch = NULL;
183
184
75.4k
  if(res==NULL)
185
0
    return -1;
186
187
75.4k
  ch = sint2str(sival, &l);
188
75.4k
  res->rs.s = ch;
189
75.4k
  res->rs.len = l;
190
191
75.4k
  res->ri = sival;
192
75.4k
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
193
75.4k
  return 0;
194
75.4k
}
195
196
/**
197
 * convert str to pv_value_t
198
 */
199
int pv_get_strval(struct sip_msg *msg, pv_param_t *param,
200
    pv_value_t *res, str *sval)
201
104k
{
202
104k
  if(res==NULL)
203
0
    return -1;
204
205
104k
  res->rs = *sval;
206
104k
  res->flags = PV_VAL_STR;
207
104k
  return 0;
208
104k
}
209
210
/**
211
 * convert str-int to pv_value_t (type is str)
212
 */
213
static int pv_get_strintval(struct sip_msg *msg, pv_param_t *param,
214
    pv_value_t *res, str *sval, int ival)
215
26.0k
{
216
26.0k
  if(res==NULL)
217
0
    return -1;
218
219
26.0k
  res->rs = *sval;
220
26.0k
  res->ri = ival;
221
26.0k
  res->flags = PV_VAL_STR|PV_VAL_INT;
222
26.0k
  return 0;
223
26.0k
}
224
225
/**
226
 * convert int-str to pv_value_t (type is int)
227
 */
228
static int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param,
229
    pv_value_t *res, int ival, str *sval)
230
69
{
231
69
  if(res==NULL)
232
0
    return -1;
233
234
69
  res->rs = *sval;
235
69
  res->ri = ival;
236
69
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
237
69
  return 0;
238
69
}
239
240
/************************************************************/
241
static int pv_get_marker(struct sip_msg *msg, pv_param_t *param,
242
    pv_value_t *res)
243
0
{
244
0
  return pv_get_strintval(msg, param, res, &str_marker, (int)str_marker.s[0]);
245
0
}
246
247
int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
248
824k
{
249
824k
  if(res==NULL)
250
0
    return -1;
251
252
824k
  res->rs = str_empty;
253
824k
  res->ri = 0;
254
824k
  res->flags = PV_VAL_NULL;
255
824k
  return 0;
256
824k
}
257
258
/************************************************************/
259
static int pv_get_pid(struct sip_msg *msg, pv_param_t *param,
260
    pv_value_t *res)
261
10.7k
{
262
10.7k
  if(_pv_pid == 0)
263
1
    _pv_pid = (int)getpid();
264
10.7k
  return pv_get_sintval(msg, param, res, _pv_pid);
265
10.7k
}
266
267
268
extern int return_code;
269
static int pv_get_return_code(struct sip_msg *msg, pv_param_t *param,
270
    pv_value_t *res)
271
21.5k
{
272
21.5k
  return pv_get_sintval(msg, param, res, return_code);
273
21.5k
}
274
275
static int pv_get_route(struct sip_msg *msg, pv_param_t *param,
276
    pv_value_t *res)
277
10.7k
{
278
10.7k
  static str rn_buf;
279
280
10.7k
  str s;
281
10.7k
  int i, idx, idx_flags, len, rlen, has_name, route_stack_size_ctx;
282
283
10.7k
  if (pv_get_spec_index(msg, param, &idx, &idx_flags) != 0) {
284
0
    LM_ERR("invalid index\n");
285
0
    return -1;
286
0
  }
287
288
10.7k
  if (idx_flags == PV_IDX_ALL) {
289
0
    get_top_route_type(&s, &has_name);
290
0
    if (!has_name)
291
0
      goto unnamed_route;
292
293
0
    len = strlen(route_stack[route_stack_start]);
294
0
    if (pkg_str_extend(&rn_buf, s.len + 2 + len + 1) != 0) {
295
0
      LM_ERR("oom\n");
296
0
      return pv_get_null(msg, param, res);
297
0
    }
298
299
0
    len = sprintf(rn_buf.s, "%.*s[%s]", s.len, s.s, route_stack[route_stack_start]);
300
0
    goto print_remaining;
301
302
0
  unnamed_route:
303
0
    if (pkg_str_extend(&rn_buf, s.len + 1) != 0) {
304
0
      LM_ERR("oom\n");
305
0
      return pv_get_null(msg, param, res);
306
0
    }
307
308
0
    len = sprintf(rn_buf.s, "%.*s", s.len, s.s);
309
310
0
  print_remaining:
311
0
    s = str_route;
312
313
0
    for (i = route_stack_start+1; i < route_stack_size; i++) {
314
0
      if (!route_stack[i]) {
315
0
        if (pkg_str_extend(&rn_buf, len + 3 + s.len + 1) != 0) {
316
0
          LM_ERR("oom\n");
317
0
          return pv_get_null(msg, param, res);
318
0
        }
319
320
0
        len += sprintf(rn_buf.s + len, " > %.*s", s.len, s.s);
321
0
      } else if (route_stack[i][0] != '!') {
322
0
        rlen = strlen(route_stack[i]);
323
324
0
        if (pkg_str_extend(&rn_buf, len + s.len + 5 + rlen + 1) != 0) {
325
0
          LM_ERR("oom\n");
326
0
          return pv_get_null(msg, param, res);
327
0
        }
328
329
0
        len += sprintf(rn_buf.s + len, " > %.*s[%s]",
330
0
                  s.len, s.s, route_stack[i]);
331
0
      } else {
332
0
        rlen = strlen(route_stack[i]);
333
334
        /* the "!" marker tells us to print that route name as-is */
335
0
        if (pkg_str_extend(&rn_buf, len + rlen + 3) != 0) {
336
0
          LM_ERR("oom\n");
337
0
          return pv_get_null(msg, param, res);
338
0
        }
339
340
0
        len += sprintf(rn_buf.s + len, " > %s", route_stack[i] + 1);
341
0
      }
342
0
    }
343
344
0
    s.s = rn_buf.s;
345
0
    s.len = len;
346
0
    return pv_get_strval(msg, param, res, &s);
347
0
  }
348
349
10.7k
  route_stack_size_ctx = route_stack_size - route_stack_start;
350
351
10.7k
  if (idx < 0)
352
0
    idx += route_stack_size_ctx;
353
354
  /* index out of bounds -- play nice and return NULL */
355
10.7k
  if (idx > route_stack_size_ctx - 1 || idx < 0)
356
10.7k
    return pv_get_null(msg, param, res);
357
358
  /* reverse the index, since we index the route stack backwards */
359
0
  idx = route_stack_size_ctx - idx - 1;
360
361
0
  if (idx == 0) {
362
0
    get_top_route_type(&s, &has_name);
363
0
    if (!has_name)
364
0
      goto out_ok;
365
366
0
  } else {
367
0
    s = str_route;
368
0
    if (!route_stack[route_stack_start + idx])
369
0
      goto out_ok;
370
0
  }
371
372
0
  len = strlen(route_stack[route_stack_start + idx]);
373
374
0
  if (route_stack[route_stack_start + idx][0] != '!') {
375
0
    if (pkg_str_extend(&rn_buf, s.len + 2 + len + 1) != 0) {
376
0
      LM_ERR("oom\n");
377
0
      return pv_get_null(msg, param, res);
378
0
    }
379
380
0
    s.len = sprintf(rn_buf.s, "%.*s[%s]", s.len, s.s, route_stack[route_stack_start + idx]);
381
0
    s.s = rn_buf.s;
382
0
  } else {
383
    /* the "!" marker tells us to print that route name as-is */
384
0
    if (pkg_str_extend(&rn_buf, len) != 0) {
385
0
      LM_ERR("oom\n");
386
0
      return pv_get_null(msg, param, res);
387
0
    }
388
389
0
    s.len = sprintf(rn_buf.s, "%s", route_stack[route_stack_start + idx] + 1);
390
0
    s.s = rn_buf.s;
391
0
  }
392
393
0
out_ok:
394
0
  return pv_get_strval(msg, param, res, &s);
395
0
}
396
397
398
static int pv_get_route_name(struct sip_msg *msg, pv_param_t *param,
399
    pv_value_t *res)
400
10.7k
{
401
10.7k
  str rn;
402
10.7k
  int idx, idx_flags, route_stack_size_ctx;
403
404
10.7k
  if (pv_get_spec_index(msg, param, &idx, &idx_flags) != 0) {
405
0
    LM_ERR("invalid index\n");
406
0
    return -1;
407
0
  }
408
409
10.7k
  if (idx_flags == PV_IDX_ALL) {
410
0
    LM_ERR("unsupported index: [*]\n");
411
0
    return -1;
412
0
  }
413
414
10.7k
  route_stack_size_ctx = route_stack_size - route_stack_start;
415
416
10.7k
  if (idx < 0)
417
0
    idx += route_stack_size_ctx;
418
419
  /* index out of bounds -- play nice and return NULL */
420
10.7k
  if (idx > route_stack_size_ctx - 1 || idx < 0)
421
10.7k
    return pv_get_null(msg, param, res);
422
423
  /* reverse the index, since we index the route stack backwards */
424
0
  idx = route_stack_size_ctx - idx - 1;
425
426
0
  get_route_name(idx, &rn);
427
0
  return pv_get_strval(msg, param, res, &rn);
428
10.7k
}
429
430
431
static int pv_get_route_type(struct sip_msg *msg, pv_param_t *param,
432
    pv_value_t *res)
433
10.7k
{
434
10.7k
  str rt;
435
10.7k
  int idx, idx_flags, route_stack_size_ctx;
436
437
10.7k
  if (pv_get_spec_index(msg, param, &idx, &idx_flags) != 0) {
438
0
    LM_ERR("invalid index\n");
439
0
    return -1;
440
0
  }
441
442
10.7k
  if (idx_flags == PV_IDX_ALL) {
443
0
    LM_ERR("unsupported index: [*]\n");
444
0
    return -1;
445
0
  }
446
447
10.7k
  route_stack_size_ctx = route_stack_size - route_stack_start;
448
449
10.7k
  if (idx < 0)
450
0
    idx += route_stack_size_ctx;
451
452
  /* index out of bounds -- play nice and return NULL */
453
10.7k
  if (idx > route_stack_size_ctx - 1 || idx < 0)
454
10.7k
    return pv_get_null(msg, param, res);
455
456
  /* reverse the index, since we index the route stack backwards */
457
0
  idx = route_stack_size_ctx - idx - 1;
458
459
0
  get_route_type(idx, &rt);
460
0
  return pv_get_strval(msg, param, res, &rt);
461
10.7k
}
462
463
464
static int pv_get_times(struct sip_msg *msg, pv_param_t *param,
465
    pv_value_t *res)
466
10.7k
{
467
10.7k
  if(msg==NULL)
468
0
    return -1;
469
470
10.7k
  return pv_get_uintval(msg, param, res, (unsigned int)time(NULL));
471
10.7k
}
472
473
static int pv_get_timem(struct sip_msg *msg, pv_param_t *param,
474
    pv_value_t *res)
475
10.7k
{
476
10.7k
  struct timeval TP;
477
478
10.7k
  if(msg==NULL)
479
0
    return -1;
480
481
10.7k
  gettimeofday(&TP, NULL);
482
10.7k
  return pv_get_uintval(msg, param, res, (unsigned int)TP.tv_usec);
483
10.7k
}
484
485
static int pv_get_start_times(struct sip_msg *msg, pv_param_t *param,
486
    pv_value_t *res)
487
10.7k
{
488
10.7k
  if(msg==NULL)
489
0
    return -1;
490
491
10.7k
  return pv_get_uintval(msg, param, res, (unsigned int)startup_time);
492
10.7k
}
493
494
static int pv_parse_time_name(pv_spec_p sp, const str *in)
495
0
{
496
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
497
0
  sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
498
0
  sp->pvp.pvn.u.isname.name.s.s = pkg_malloc(in->len + 1);
499
0
  if (sp->pvp.pvn.u.isname.name.s.s==NULL) {
500
0
    LM_ERR("failed to allocated private mem\n");
501
0
    return -1;
502
0
  }
503
0
  memcpy(sp->pvp.pvn.u.isname.name.s.s, in->s, in->len);
504
0
  sp->pvp.pvn.u.isname.name.s.s[in->len] = 0;
505
0
  sp->pvp.pvn.u.isname.name.s.len = in->len;
506
0
  return 0;
507
0
}
508
509
static int pv_get_formated_time(struct sip_msg *msg, pv_param_t *param,
510
    pv_value_t *res)
511
0
{
512
0
  static char buf[128];
513
0
  struct tm ltime;
514
0
  time_t t;
515
516
0
  if(msg==NULL)
517
0
    return -1;
518
519
0
  time( &t );
520
0
  localtime_r(&t, &ltime);
521
0
  res->rs.len = strftime( buf, 127, param->pvn.u.isname.name.s.s, &ltime);
522
523
0
  if (res->rs.len<=0)
524
0
    return pv_get_null(msg, param, res);
525
526
0
  res->rs.s = buf;
527
0
  res->flags = PV_VAL_STR;
528
0
  return 0;
529
0
}
530
531
10.7k
#define CTIME_BUFFER_NO 5
532
#define CTIME_BUFFER_SIZE 26
533
534
static int pv_get_timef(struct sip_msg *msg, pv_param_t *param,
535
    pv_value_t *res)
536
10.7k
{
537
10.7k
  static char ctime_bufs[CTIME_BUFFER_NO][CTIME_BUFFER_SIZE];
538
10.7k
  static char *buf;
539
10.7k
  static int ctime_buf_no = 0;
540
10.7k
  time_t t;
541
10.7k
  str s;
542
543
10.7k
  if(msg==NULL)
544
0
    return -1;
545
546
10.7k
  t = time(NULL);
547
10.7k
  buf = ctime_bufs[ctime_buf_no];
548
10.7k
  ctime_buf_no = (ctime_buf_no + 1) % CTIME_BUFFER_NO;
549
10.7k
  s.s = ctime_r(&t, buf);
550
10.7k
  s.len = strlen(s.s)-1;
551
10.7k
  return pv_get_strintval(msg, param, res, &s, (int)t);
552
10.7k
}
553
554
static int pv_get_msgid(struct sip_msg *msg, pv_param_t *param,
555
    pv_value_t *res)
556
10.7k
{
557
10.7k
  if(msg==NULL)
558
0
    return -1;
559
10.7k
  return pv_get_uintval(msg, param, res, msg->id);
560
10.7k
}
561
562
static int pv_get_method(struct sip_msg *msg, pv_param_t *param,
563
    pv_value_t *res)
564
10.7k
{
565
10.7k
  if(msg==NULL)
566
0
    return -1;
567
568
10.7k
  if(msg->first_line.type == SIP_REQUEST)
569
10.7k
  {
570
10.7k
    return pv_get_strintval(msg, param, res,
571
10.7k
        &msg->first_line.u.request.method,
572
10.7k
        (int)msg->first_line.u.request.method_value);
573
10.7k
  }
574
575
4
  if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1) ||
576
3
        (msg->cseq==NULL)))
577
3
  {
578
3
    LM_ERR("no CSEQ header\n");
579
3
    return pv_get_null(msg, param, res);
580
3
  }
581
582
1
  return pv_get_strintval(msg, param, res,
583
1
      &get_cseq(msg)->method,
584
1
      get_cseq(msg)->method_id);
585
4
}
586
587
static int pv_get_status(struct sip_msg *msg, pv_param_t *param,
588
    pv_value_t *res)
589
10.7k
{
590
10.7k
  if(msg==NULL)
591
0
    return -1;
592
593
10.7k
  if(msg->first_line.type != SIP_REPLY)
594
10.7k
    return pv_get_null(msg, param, res);
595
596
4
  return pv_get_intstrval(msg, param, res,
597
4
      (int)msg->first_line.u.reply.statuscode,
598
4
      &msg->first_line.u.reply.status);
599
10.7k
}
600
601
static int pv_get_reason(struct sip_msg *msg, pv_param_t *param,
602
    pv_value_t *res)
603
10.7k
{
604
10.7k
  if(msg==NULL)
605
0
    return -1;
606
607
10.7k
  if(msg->first_line.type != SIP_REPLY)
608
10.7k
    return pv_get_null(msg, param, res);
609
610
4
  return pv_get_strval(msg, param, res, &msg->first_line.u.reply.reason);
611
10.7k
}
612
613
static int pv_get_ruri(struct sip_msg *msg, pv_param_t *param,
614
    pv_value_t *res)
615
21.5k
{
616
21.5k
  if(msg==NULL || res==NULL)
617
0
    return -1;
618
619
21.5k
  if(msg->first_line.type == SIP_REPLY)  /* REPLY doesn't have a ruri */
620
8
    return pv_get_null(msg, param, res);
621
622
21.5k
  if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0)
623
17.5k
  {
624
17.5k
    LM_ERR("failed to parse the R-URI\n");
625
17.5k
    return pv_get_null(msg, param, res);
626
17.5k
  }
627
628
3.95k
  if (msg->new_uri.s!=NULL)
629
0
    return pv_get_strval(msg, param, res, &msg->new_uri);
630
3.95k
  return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri);
631
3.95k
}
632
633
static int pv_get_ru_q(struct sip_msg *msg, pv_param_t *param,
634
    pv_value_t *res)
635
10.7k
{
636
10.7k
  if(msg==NULL || res==NULL)
637
0
    return -1;
638
639
10.7k
  if(msg->first_line.type == SIP_REPLY)
640
4
    return pv_get_null(msg, param, res);
641
642
10.7k
  return pv_get_sintval(msg, param, res, get_ruri_q(msg));
643
10.7k
}
644
645
static int pv_get_ouri(struct sip_msg *msg, pv_param_t *param,
646
    pv_value_t *res)
647
21.5k
{
648
21.5k
  if(msg==NULL || res==NULL)
649
0
    return -1;
650
651
21.5k
  if(msg->first_line.type == SIP_REPLY)  /* REPLY doesn't have a ruri */
652
8
    return pv_get_null(msg, param, res);
653
654
21.5k
  if(msg->parsed_orig_ruri_ok==0
655
21.5k
      /* orig R-URI not parsed*/ && parse_orig_ruri(msg)<0)
656
17.5k
  {
657
17.5k
    LM_ERR("failed to parse the R-URI\n");
658
17.5k
    return pv_get_null(msg, param, res);
659
17.5k
  }
660
3.95k
  return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri);
661
21.5k
}
662
663
static int pv_get_xuri_attr(struct sip_msg *msg, struct sip_uri *parsed_uri,
664
    pv_param_t *param, pv_value_t *res)
665
19.7k
{
666
19.7k
  unsigned short proto;
667
19.7k
  str proto_s;
668
669
19.7k
  if(param->pvn.u.isname.name.n==1) /* username */
670
5.93k
  {
671
5.93k
    if(parsed_uri->user.s==NULL || parsed_uri->user.len<=0)
672
4.03k
      return pv_get_null(msg, param, res);
673
1.90k
    return pv_get_strval(msg, param, res, &parsed_uri->user);
674
13.8k
  } else if(param->pvn.u.isname.name.n==2) /* domain */ {
675
5.93k
    if(parsed_uri->host.s==NULL || parsed_uri->host.len<=0)
676
18
      return pv_get_null(msg, param, res);
677
5.91k
    return pv_get_strval(msg, param, res, &parsed_uri->host);
678
7.91k
  } else if(param->pvn.u.isname.name.n==3) /* port */ {
679
3.95k
    if(parsed_uri->port.s==NULL)
680
3.44k
      return pv_get_uintval(msg, param, res,
681
3.44k
        get_uri_port( parsed_uri, &proto));
682
510
    return pv_get_strintval(msg, param, res, &parsed_uri->port,
683
510
        (int)parsed_uri->port_no);
684
3.95k
  } else if(param->pvn.u.isname.name.n==4) /* protocol */ {
685
3.95k
    if(parsed_uri->transport_val.s==NULL) {
686
3.43k
      get_uri_port(parsed_uri, &proto);
687
3.43k
      proto_s.s = protos[proto].name;
688
3.43k
      proto_s.len = proto_s.s ? strlen(proto_s.s) : 0;
689
3.43k
      return pv_get_strintval(msg, param, res, &proto_s, (int)proto);
690
3.43k
    }
691
522
    return pv_get_strintval(msg, param, res, &parsed_uri->transport_val,
692
522
        (int)parsed_uri->proto);
693
3.95k
  }
694
0
  LM_ERR("unknown specifier\n");
695
0
  return pv_get_null(msg, param, res);
696
19.7k
}
697
698
static int pv_get_ruri_attr(struct sip_msg *msg, pv_param_t *param,
699
    pv_value_t *res)
700
64.6k
{
701
64.6k
  if(msg==NULL)
702
0
    return -1;
703
704
64.6k
  if(msg->first_line.type == SIP_REPLY)  /* REPLY doesn't have a ruri */
705
24
    return pv_get_null(msg, param, res);
706
707
64.6k
  if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0)
708
52.7k
  {
709
52.7k
    LM_ERR("failed to parse the R-URI\n");
710
52.7k
    return pv_get_null(msg, param, res);
711
52.7k
  }
712
11.8k
  return pv_get_xuri_attr(msg, &(msg->parsed_uri), param, res);
713
64.6k
}
714
715
static int pv_get_ouri_attr(struct sip_msg *msg, pv_param_t *param,
716
    pv_value_t *res)
717
43.1k
{
718
43.1k
  if(msg==NULL)
719
0
    return -1;
720
721
43.1k
  if(msg->first_line.type == SIP_REPLY)  /* REPLY doesn't have a ruri */
722
16
    return pv_get_null(msg, param, res);
723
724
43.0k
  if(msg->parsed_orig_ruri_ok==0
725
43.0k
      /* orig R-URI not parsed*/ && parse_orig_ruri(msg)<0)
726
35.1k
  {
727
35.1k
    LM_ERR("failed to parse the R-URI\n");
728
35.1k
    return pv_get_null(msg, param, res);
729
35.1k
  }
730
7.91k
  return pv_get_xuri_attr(msg, &(msg->parsed_orig_ruri), param, res);
731
43.0k
}
732
733
static int pv_get_path(struct sip_msg *msg, pv_param_t *param,
734
    pv_value_t *res)
735
10.7k
{
736
10.7k
  if(msg==NULL)
737
0
    return -1;
738
739
10.7k
  if(!msg->path_vec.s)
740
10.7k
  {
741
10.7k
    return pv_get_null(msg, param, res);
742
10.7k
  }
743
0
  return pv_get_strval(msg, param, res, &msg->path_vec);
744
10.7k
}
745
746
0
#define CT_NAME_S        "name"
747
0
#define CT_NAME_LEN      (sizeof(CT_NAME_S)-1)
748
0
#define CT_NAME_ID       1
749
0
#define CT_URI_S         "uri"
750
0
#define CT_URI_LEN       (sizeof(CT_URI_S)-1)
751
0
#define CT_URI_ID        2
752
0
#define CT_Q_S           "q"
753
0
#define CT_Q_LEN         (sizeof(CT_Q_S)-1)
754
0
#define CT_Q_ID          3
755
0
#define CT_EXPIRES_S     "expires"
756
0
#define CT_EXPIRES_LEN   (sizeof(CT_EXPIRES_S)-1)
757
0
#define CT_EXPIRES_ID     4
758
0
#define CT_METHODS_S     "methods"
759
0
#define CT_METHODS_LEN   (sizeof(CT_METHODS_S)-1)
760
0
#define CT_METHODS_ID    5
761
0
#define CT_RECEIVED_S    "received"
762
0
#define CT_RECEIVED_LEN  (sizeof(CT_RECEIVED_S)-1)
763
0
#define CT_RECEIVED_ID   6
764
0
#define CT_PARAMS_S      "params"
765
0
#define CT_PARAMS_LEN    (sizeof(CT_PARAMS_S)-1)
766
0
#define CT_PARAMS_ID     7
767
768
static int pv_parse_ct_name(pv_spec_p sp, const str *in)
769
0
{
770
0
  if (sp==NULL)
771
0
    return -1;
772
773
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
774
0
  sp->pvp.pvn.u.isname.type = 0;
775
776
0
  if (in==NULL || in->s==NULL || in->len==0) {
777
0
    sp->pvp.pvn.u.isname.name.n = 0;
778
0
  } else
779
0
  if (in->len==CT_NAME_LEN &&
780
0
  strncasecmp(in->s, CT_NAME_S, CT_NAME_LEN)==0 ) {
781
0
    sp->pvp.pvn.u.isname.name.n = CT_NAME_ID;
782
0
  } else
783
0
  if (in->len==CT_URI_LEN &&
784
0
  strncasecmp(in->s, CT_URI_S, CT_URI_LEN)==0 ) {
785
0
    sp->pvp.pvn.u.isname.name.n = CT_URI_ID;
786
0
  } else
787
0
  if (in->len==CT_Q_LEN &&
788
0
  strncasecmp(in->s, CT_Q_S, CT_Q_LEN)==0 ) {
789
0
    sp->pvp.pvn.u.isname.name.n = CT_Q_ID;
790
0
  } else
791
0
  if (in->len==CT_EXPIRES_LEN &&
792
0
  strncasecmp(in->s, CT_EXPIRES_S, CT_EXPIRES_LEN)==0 ) {
793
0
    sp->pvp.pvn.u.isname.name.n = CT_EXPIRES_ID;
794
0
  } else
795
0
  if (in->len==CT_METHODS_LEN &&
796
0
  strncasecmp(in->s, CT_METHODS_S, CT_METHODS_LEN)==0 ) {
797
0
    sp->pvp.pvn.u.isname.name.n = CT_METHODS_ID;
798
0
  } else
799
0
  if (in->len==CT_RECEIVED_LEN &&
800
0
  strncasecmp(in->s, CT_RECEIVED_S, CT_RECEIVED_LEN)==0 ) {
801
0
    sp->pvp.pvn.u.isname.name.n = CT_RECEIVED_ID;
802
0
  } else
803
0
  if (in->len==CT_PARAMS_LEN &&
804
0
  strncasecmp(in->s, CT_PARAMS_S, CT_PARAMS_LEN)==0 ) {
805
0
    sp->pvp.pvn.u.isname.name.n = CT_PARAMS_ID;
806
0
  } else {
807
0
    LM_ERR("unsupported CT field <%.*s>\n",in->len,in->s);
808
0
    return -1;
809
0
  }
810
811
0
  return 0;
812
0
}
813
814
815
static inline int get_contact_body_field(pv_value_t *res,struct hdr_field *cth,
816
                    contact_t *ct, pv_name_t *pvn)
817
557
{
818
557
  param_t *p;
819
820
557
  if (ct==NULL) {
821
    /* star contact hdr */
822
1
    if (pvn->u.isname.name.n==0) {
823
1
      res->rs = cth->body;
824
1
      res->flags = PV_VAL_STR;
825
1
      return 0;
826
1
    }
827
0
    return pv_get_null(NULL, NULL, res);
828
1
  }
829
830
556
  switch (pvn->u.isname.name.n) {
831
556
    case 0: /* all body */
832
556
      res->rs.s = ct->name.s?ct->name.s:ct->uri.s;
833
556
      res->rs.len = ct->len;
834
556
      break;
835
0
    case CT_NAME_ID: /* name only */
836
0
      if (ct->name.s==NULL || ct->name.len==0)
837
0
        return pv_get_null(NULL, NULL, res);
838
0
      res->rs = ct->name;
839
0
      break;
840
0
    case CT_URI_ID: /* uri only */
841
0
      res->rs = ct->uri;
842
0
      break;
843
0
    case CT_Q_ID: /* Q param only */
844
0
      if ( !ct->q || !ct->q->body.s || !ct->q->body.len)
845
0
        return pv_get_null(NULL, NULL, res);
846
0
      res->rs = ct->q->body;
847
0
      break;
848
0
    case CT_EXPIRES_ID: /* EXPIRES param only */
849
0
      if (!ct->expires||!ct->expires->body.s||!ct->expires->body.len)
850
0
        return pv_get_null(NULL, NULL, res);
851
0
      res->rs = ct->expires->body;
852
0
      break;
853
0
    case CT_METHODS_ID: /* METHODS param only */
854
0
      if (!ct->methods||!ct->methods->body.s||!ct->methods->body.len)
855
0
        return pv_get_null(NULL, NULL, res);
856
0
      res->rs = ct->methods->body;
857
0
      break;
858
0
    case CT_RECEIVED_ID: /* RECEIVED param only */
859
0
      if(!ct->received||!ct->received->body.s||!ct->received->body.len)
860
0
        return pv_get_null(NULL, NULL, res);
861
0
      res->rs = ct->received->body;
862
0
      break;
863
0
    case CT_PARAMS_ID: /* all param */
864
0
      if (!ct->params)
865
0
        return pv_get_null(NULL, NULL, res);
866
0
      res->rs.s = ct->params->name.s;
867
0
      for( p=ct->params ; p->next ; p=p->next);
868
0
      res->rs.len = p->name.s + p->len - res->rs.s;
869
0
      break;
870
0
    default:
871
0
      LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.type);
872
0
      return pv_get_null(NULL, NULL, res);
873
556
  }
874
875
556
  res->flags = PV_VAL_STR;
876
556
  return 0;
877
556
}
878
879
880
static int pv_get_contact_body(struct sip_msg *msg, pv_param_t *param,
881
    pv_value_t *res)
882
10.7k
{
883
10.7k
  struct hdr_field *ct_h;
884
10.7k
  contact_body_t *ct_b;
885
10.7k
  contact_t *ct;
886
10.7k
  int idx;
887
10.7k
  int idxf;
888
10.7k
  char *p;
889
890
10.7k
  if(msg==NULL)
891
0
    return -1;
892
893
  /* get all CONTACT headers */
894
10.7k
  if(parse_headers(msg, HDR_EOH_F, 0)==-1 || msg->contact==NULL ||
895
10.7k
  !msg->contact->body.s || msg->contact->body.len<=0)
896
9.68k
  {
897
9.68k
    LM_DBG("no contact header!\n");
898
9.68k
    return pv_get_null(msg, param, res);
899
9.68k
  }
900
901
1.09k
  ct_h = msg->contact;
902
1.09k
  if (parse_contact( ct_h )!=0) {
903
538
    LM_ERR("failed to parse contact hdr\n");
904
538
    return -1;
905
538
  }
906
557
  ct_b = (contact_body_t*)ct_h->parsed;
907
557
  if (ct_b==NULL)
908
0
    return pv_get_null(msg, param, res);
909
557
  ct = ct_b->contacts;
910
911
  /* get the index */
912
557
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
913
0
    LM_ERR("invalid index\n");
914
0
    return -1;
915
0
  }
916
917
557
  if( idxf!=PV_IDX_ALL && idx==0) {
918
    /* no index specified -> return the first contact body */
919
557
    return get_contact_body_field( res , ct_h, ct, &param->pvn);
920
557
  }
921
922
0
  if(idxf==PV_IDX_ALL) {
923
    /* return all contact bodies */
924
0
    p = pv_local_buf;
925
0
    do {
926
0
      if(p!=pv_local_buf) {
927
0
        if (p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE){
928
0
          LM_ERR("local buffer length exceeded\n");
929
0
          return pv_get_null(msg, param, res);
930
0
        }
931
0
        memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
932
0
        p += PV_FIELD_DELIM_LEN;
933
0
      }
934
935
0
      get_contact_body_field( res , ct_h, ct, &param->pvn);
936
0
      if (p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE) {
937
0
        LM_ERR("local buffer length exceeded!\n");
938
0
        return pv_get_null(msg, param, res);
939
0
      }
940
0
      memcpy(p, res->rs.s, res->rs.len);
941
0
      p += res->rs.len;
942
943
0
      ct = ct?ct->next:NULL;
944
0
      while (ct==NULL && ct_h!=NULL) {
945
0
        ct_h = ct_h->sibling;
946
0
        if (ct_h) {
947
0
          if (parse_contact( ct_h )!=0) {
948
0
            LM_ERR("failed to parse contact hdr\n");
949
0
            return -1;
950
0
          }
951
0
          ct_b = (contact_body_t*)ct_h->parsed;
952
0
          ct = ct_b->contacts;
953
0
        }
954
0
      }
955
0
    } while (ct_h);
956
957
0
    res->rs.s = pv_local_buf;
958
0
    res->rs.len = p - pv_local_buf;
959
0
    res->flags = PV_VAL_STR;
960
0
    return 0;
961
0
  }
962
963
  /* numerical index */
964
0
  if (idx<0) {
965
    /* index from the end */
966
0
    idxf=0;
967
0
    while(ct_h) {
968
0
      idxf++;
969
0
      ct = ct?ct->next:NULL;
970
0
      while (ct==NULL && ct_h!=NULL) {
971
0
        ct_h = ct_h->sibling;
972
0
        if (ct_h) {
973
0
          if (parse_contact( ct_h)!=0) {
974
0
            LM_ERR("failed to parse contact hdr\n");
975
0
            return -1;
976
0
          }
977
0
          ct_b = (contact_body_t*)ct_h->parsed;
978
0
          ct = ct_b->contacts;
979
0
        }
980
0
      }
981
0
    }
982
0
    if (-idx>idxf)
983
0
      return pv_get_null(msg, param, res);
984
985
0
    idx = idxf +idx;
986
0
    ct_h = msg->contact;
987
0
    ct_b = (contact_body_t*)ct_h->parsed;
988
0
    ct = ct_b->contacts;
989
0
  }
990
991
0
  while (idx!=0 && ct_h) {
992
    /* get to the next contact body */
993
0
    idx--;
994
0
    ct = ct?ct->next:NULL;
995
0
    while (ct==NULL && ct_h!=NULL) {
996
0
      ct_h = ct_h->sibling;
997
0
      if (ct_h) {
998
0
        if (parse_contact( ct_h )!=0) {
999
0
          LM_ERR("failed to parse contact hdr\n");
1000
0
          return -1;
1001
0
        }
1002
0
        ct_b = (contact_body_t*)ct_h->parsed;
1003
0
        ct = ct_b->contacts;
1004
0
      }
1005
0
    }
1006
0
  }
1007
1008
  /* nothing found ?*/
1009
0
  if (ct==NULL)
1010
0
    return pv_get_null(msg, param, res);
1011
1012
  /* take the current body */
1013
0
  return get_contact_body_field( res , ct_h, ct, &param->pvn);
1014
0
}
1015
1016
extern err_info_t _oser_err_info;
1017
static int pv_get_errinfo_attr(struct sip_msg *msg, pv_param_t *param,
1018
    pv_value_t *res)
1019
53.8k
{
1020
53.8k
  if(msg==NULL)
1021
0
    return -1;
1022
1023
53.8k
  if(param->pvn.u.isname.name.n==0) /* class */ {
1024
10.7k
    return pv_get_sintval(msg, param, res, _oser_err_info.eclass);
1025
43.1k
  } else if(param->pvn.u.isname.name.n==1) /* level */ {
1026
10.7k
    return pv_get_sintval(msg, param, res, _oser_err_info.level);
1027
32.3k
  } else if(param->pvn.u.isname.name.n==2) /* info */ {
1028
10.7k
    if(_oser_err_info.info.s==NULL)
1029
0
      pv_get_null(msg, param, res);
1030
10.7k
    return pv_get_strval(msg, param, res, &_oser_err_info.info);
1031
21.5k
  } else if(param->pvn.u.isname.name.n==3) /* rcode */ {
1032
10.7k
    return pv_get_sintval(msg, param, res, _oser_err_info.rcode);
1033
10.7k
  } else if(param->pvn.u.isname.name.n==4) /* rreason */ {
1034
10.7k
    if(_oser_err_info.rreason.s==NULL)
1035
0
      pv_get_null(msg, param, res);
1036
10.7k
    return pv_get_strval(msg, param, res, &_oser_err_info.rreason);
1037
10.7k
  } else {
1038
0
    LM_DBG("invalid attribute!\n");
1039
0
    return pv_get_null(msg, param, res);
1040
0
  }
1041
53.8k
}
1042
1043
static int pv_get_xto_attr(struct sip_msg *msg, pv_param_t *param,
1044
    pv_value_t *res, struct to_body *xto, int type)
1045
27.1k
{
1046
27.1k
  struct sip_uri *uri;
1047
27.1k
  if(xto==NULL)
1048
0
    return -1;
1049
1050
27.1k
  if(param->pvn.u.isname.name.n==1) /* uri */
1051
6.77k
    return pv_get_strval(msg, param, res, &xto->uri);
1052
1053
20.3k
  if(param->pvn.u.isname.name.n==4) /* tag */
1054
3.38k
  {
1055
3.38k
    if (xto->tag_value.s==NULL || xto->tag_value.len<=0)
1056
3.38k
    {
1057
3.38k
            LM_DBG("no Tag parameter\n");
1058
3.38k
            return pv_get_null(msg, param, res);
1059
3.38k
    }
1060
8
    return pv_get_strval(msg, param, res, &xto->tag_value);
1061
3.38k
  }
1062
1063
16.9k
  if(param->pvn.u.isname.name.n==5) /* display name */
1064
3.38k
  {
1065
3.38k
    if(xto->display.s==NULL || xto->display.len<=0)
1066
3.19k
    {
1067
3.19k
      LM_DBG("no Display name\n");
1068
3.19k
      return pv_get_null(msg, param, res);
1069
3.19k
    }
1070
194
    return pv_get_strval(msg, param, res, &xto->display);
1071
3.38k
  }
1072
1073
13.5k
  if(type==0)
1074
12.9k
  {
1075
12.9k
    if((uri=parse_to_uri(msg))==NULL)
1076
5.83k
    {
1077
5.83k
      LM_ERR("cannot parse To URI\n");
1078
5.83k
      return pv_get_null(msg, param, res);
1079
5.83k
    }
1080
12.9k
  } else {
1081
612
    if((uri=parse_from_uri(msg))==NULL)
1082
184
    {
1083
184
      LM_ERR("cannot parse From URI\n");
1084
184
      return pv_get_null(msg, param, res);
1085
184
    }
1086
612
  }
1087
1088
7.53k
  if(param->pvn.u.isname.name.n==2) /* username */
1089
3.76k
  {
1090
3.76k
      if(uri->user.s==NULL || uri->user.len<=0)
1091
2.61k
    {
1092
2.61k
        LM_DBG("no username\n");
1093
2.61k
      return pv_get_null(msg, param, res);
1094
2.61k
    }
1095
1.15k
    return pv_get_strval(msg, param, res, &uri->user);
1096
3.76k
  } else if(param->pvn.u.isname.name.n==3) /* domain */ {
1097
3.76k
      if(uri->host.s==NULL || uri->host.len<=0)
1098
16
    {
1099
16
        LM_DBG("no domain\n");
1100
16
      return pv_get_null(msg, param, res);
1101
16
    }
1102
3.75k
    return pv_get_strval(msg, param, res, &uri->host);
1103
3.76k
  }
1104
1105
0
  LM_ERR("unknown specifier\n");
1106
0
  return pv_get_null(msg, param, res);
1107
7.53k
}
1108
1109
static int pv_get_to_attr(struct sip_msg *msg, pv_param_t *param,
1110
    pv_value_t *res)
1111
86.2k
{
1112
86.2k
  if(msg==NULL)
1113
0
    return -1;
1114
1115
86.2k
  if(msg->to==NULL && parse_headers(msg, HDR_TO_F, 0)==-1)
1116
0
  {
1117
0
    LM_ERR("cannot parse To header\n");
1118
0
    return pv_get_null(msg, param, res);
1119
0
  }
1120
86.2k
  if(msg->to==NULL || get_to(msg)==NULL) {
1121
60.3k
    LM_DBG("no To header\n");
1122
60.3k
    return pv_get_null(msg, param, res);
1123
60.3k
  }
1124
25.8k
  return pv_get_xto_attr(msg, param, res, get_to(msg), 0);
1125
86.2k
}
1126
1127
static int pv_get_from_attr(struct sip_msg *msg, pv_param_t *param,
1128
    pv_value_t *res)
1129
86.2k
{
1130
86.2k
  if(msg==NULL)
1131
0
    return -1;
1132
1133
86.2k
  if(parse_from_header(msg)<0)
1134
84.9k
  {
1135
84.9k
    LM_ERR("cannot parse From header\n");
1136
84.9k
    return pv_get_null(msg, param, res);
1137
84.9k
  }
1138
1139
1.22k
  if(msg->from==NULL || get_from(msg)==NULL) {
1140
0
    LM_DBG("no From header\n");
1141
0
    return pv_get_null(msg, param, res);
1142
0
  }
1143
1.22k
  return pv_get_xto_attr(msg, param, res, get_from(msg), 1);
1144
1.22k
}
1145
1146
static int pv_get_cseq(struct sip_msg *msg, pv_param_t *param,
1147
    pv_value_t *res)
1148
10.7k
{
1149
10.7k
  if(msg==NULL)
1150
0
    return -1;
1151
1152
10.7k
  if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1)
1153
10.7k
        || (msg->cseq==NULL)) )
1154
10.7k
  {
1155
10.7k
    LM_ERR("cannot parse CSEQ header\n");
1156
10.7k
    return pv_get_null(msg, param, res);
1157
10.7k
  }
1158
26
  return pv_get_strval(msg, param, res, &(get_cseq(msg)->number));
1159
10.7k
}
1160
1161
static int pv_get_msg_buf(struct sip_msg *msg, pv_param_t *param,
1162
    pv_value_t *res)
1163
10.7k
{
1164
10.7k
  str s;
1165
10.7k
  if(msg==NULL)
1166
0
    return -1;
1167
1168
10.7k
  s.s = msg->buf;
1169
10.7k
  s.len = msg->len;
1170
10.7k
  return pv_get_strval(msg, param, res, &s);
1171
10.7k
}
1172
1173
static int pv_get_msg_len(struct sip_msg *msg, pv_param_t *param,
1174
    pv_value_t *res)
1175
10.7k
{
1176
10.7k
  if(msg==NULL)
1177
0
    return -1;
1178
1179
10.7k
  return pv_get_uintval(msg, param, res, msg->len);
1180
10.7k
}
1181
1182
static int pv_get_flags(struct sip_msg *msg, pv_param_t *param,
1183
                         pv_value_t *res)
1184
10.7k
{
1185
10.7k
  str buf;
1186
1187
10.7k
  if (!msg)
1188
0
    return -1;
1189
1190
10.7k
  buf = bitmask_to_flag_list(FLAG_TYPE_MSG, msg->flags);
1191
1192
10.7k
  return pv_get_strval(msg, param, res, &buf);
1193
10.7k
}
1194
1195
static int pv_get_bflags(struct sip_msg *msg, pv_param_t *param,
1196
    pv_value_t *res)
1197
10.7k
{
1198
10.7k
  str buf;
1199
1200
10.7k
  if (!msg)
1201
0
    return -1;
1202
1203
10.7k
  buf = bitmask_to_flag_list(FLAG_TYPE_BRANCH, getb0flags(msg));
1204
1205
10.7k
  return pv_get_strval(msg, param, res, &buf);
1206
10.7k
}
1207
1208
static int pv_get_callid(struct sip_msg *msg, pv_param_t *param,
1209
    pv_value_t *res)
1210
10.7k
{
1211
10.7k
  if(msg==NULL)
1212
0
    return -1;
1213
1214
10.7k
  if(msg->callid==NULL && ((parse_headers(msg, HDR_CALLID_F, 0)==-1) ||
1215
10.7k
        (msg->callid==NULL)) )
1216
10.7k
  {
1217
10.7k
    LM_ERR("cannot parse Call-Id header\n");
1218
10.7k
    return pv_get_null(msg, param, res);
1219
10.7k
  }
1220
1221
25
  return pv_get_strval(msg, param, res, &msg->callid->body);
1222
10.7k
}
1223
1224
static int pv_get_srcip(struct sip_msg *msg, pv_param_t *param,
1225
    pv_value_t *res)
1226
21.5k
{
1227
21.5k
  str s;
1228
21.5k
  if(msg==NULL)
1229
0
    return -1;
1230
1231
21.5k
  if ( (s.s=ip_addr2a(&msg->rcv.src_ip))==NULL)
1232
0
    return pv_get_null(msg, param, res);
1233
21.5k
  s.len = strlen(s.s);
1234
21.5k
  return pv_get_strval(msg, param, res, &s);
1235
21.5k
}
1236
1237
static int pv_get_srcport(struct sip_msg *msg, pv_param_t *param,
1238
    pv_value_t *res)
1239
10.7k
{
1240
10.7k
  if(msg==NULL)
1241
0
    return -1;
1242
10.7k
  return pv_get_uintval(msg, param, res, msg->rcv.src_port);
1243
10.7k
}
1244
1245
static int pv_get_useragent(struct sip_msg *msg, pv_param_t *param,
1246
    pv_value_t *res)
1247
10.7k
{
1248
10.7k
  if(msg==NULL)
1249
0
    return -1;
1250
10.7k
  if(msg->user_agent==NULL && ((parse_headers(msg, HDR_USERAGENT_F, 0)==-1)
1251
10.7k
       || (msg->user_agent==NULL)))
1252
10.7k
  {
1253
10.7k
    LM_DBG("no User-Agent header\n");
1254
10.7k
    return pv_get_null(msg, param, res);
1255
10.7k
  }
1256
1257
12
  return pv_get_strval(msg, param, res, &msg->user_agent->body);
1258
10.7k
}
1259
1260
static int pv_get_refer_to(struct sip_msg *msg, pv_param_t *param,
1261
    pv_value_t *res)
1262
10.7k
{
1263
10.7k
  if(msg==NULL)
1264
0
    return -1;
1265
1266
10.7k
  if(parse_refer_to_header(msg)==-1)
1267
10.7k
  {
1268
10.7k
    LM_DBG("no Refer-To header\n");
1269
10.7k
    return pv_get_null(msg, param, res);
1270
10.7k
  }
1271
1272
3
  if(msg->refer_to==NULL || get_refer_to(msg)==NULL)
1273
0
    return pv_get_null(msg, param, res);
1274
1275
3
  return pv_get_strval(msg, param, res, &(get_refer_to(msg)->uri));
1276
3
}
1277
1278
static int pv_get_diversion(struct sip_msg *msg, pv_param_t *param,
1279
    pv_value_t *res)
1280
32.3k
{
1281
32.3k
  str *val;
1282
32.3k
  str name;
1283
1284
32.3k
  if(msg == NULL)
1285
0
    return -1;
1286
1287
32.3k
  if(parse_diversion_header(msg) == -1)
1288
31.9k
  {
1289
31.9k
    LM_DBG("no Diversion header\n");
1290
31.9k
    return pv_get_null(msg, param, res);
1291
31.9k
  }
1292
1293
363
  if(msg->diversion == NULL || get_diversion(msg) == NULL)
1294
0
  {
1295
0
    LM_DBG("no Diversion header\n");
1296
0
    return pv_get_null(msg, param, res);
1297
0
  }
1298
1299
363
  if(param->pvn.u.isname.name.n == 1)  { /* uri */
1300
121
    return pv_get_strval(msg, param, res, &(get_diversion(msg)->uri));
1301
121
  }
1302
1303
242
  if(param->pvn.u.isname.name.n == 2)  { /* reason param */
1304
121
      name.s = "reason";
1305
121
      name.len = 6;
1306
121
      val = diversion_param(msg, name);
1307
121
      if (val) {
1308
3
      return pv_get_strval(msg, param, res, val);
1309
118
      } else {
1310
118
      return pv_get_null(msg, param, res);
1311
118
      }
1312
121
  }
1313
1314
121
  if(param->pvn.u.isname.name.n == 3)  { /* privacy param */
1315
121
      name.s = "privacy";
1316
121
      name.len = 7;
1317
121
      val = diversion_param(msg, name);
1318
121
      if (val) {
1319
2
      return pv_get_strval(msg, param, res, val);
1320
119
      } else {
1321
119
      return pv_get_null(msg, param, res);
1322
119
      }
1323
121
  }
1324
1325
0
  LM_ERR("unknown diversion specifier\n");
1326
0
  return pv_get_null(msg, param, res);
1327
121
}
1328
1329
static int pv_get_rpid(struct sip_msg *msg, pv_param_t *param,
1330
    pv_value_t *res)
1331
10.7k
{
1332
10.7k
  if(msg==NULL)
1333
0
    return -1;
1334
1335
10.7k
  if(parse_rpid_header(msg)==-1)
1336
10.7k
  {
1337
10.7k
    LM_DBG("no RPID header\n");
1338
10.7k
    return pv_get_null(msg, param, res);
1339
10.7k
  }
1340
1341
1
  if(msg->rpid==NULL || get_rpid(msg)==NULL)
1342
0
    return pv_get_null(msg, param, res);
1343
1344
1
  return pv_get_strval(msg, param, res, &(get_rpid(msg)->uri));
1345
1
}
1346
1347
static int pv_get_ppi_attr(struct sip_msg *msg, pv_param_t *param,
1348
    pv_value_t *res)
1349
43.1k
{
1350
43.1k
    struct sip_uri *uri;
1351
1352
43.1k
    if(msg==NULL)
1353
0
  return -1;
1354
1355
43.1k
    if(parse_ppi_header(msg) < 0) {
1356
42.4k
  LM_DBG("no P-Preferred-Identity header\n");
1357
42.4k
  return pv_get_null(msg, param, res);
1358
42.4k
    }
1359
1360
660
    if(msg->ppi == NULL || get_ppi(msg) == NULL) {
1361
0
         LM_DBG("no P-Preferred-Identity header\n");
1362
0
    return pv_get_null(msg, param, res);
1363
0
    }
1364
1365
660
    if(param->pvn.u.isname.name.n == 1) { /* uri */
1366
165
    return pv_get_strval(msg, param, res, &(get_ppi(msg)->uri));
1367
165
    }
1368
1369
495
    if(param->pvn.u.isname.name.n==4) { /* display name */
1370
165
    if(get_ppi(msg)->display.s == NULL ||
1371
165
        get_ppi(msg)->display.len <= 0) {
1372
128
        LM_DBG("no P-Preferred-Identity display name\n");
1373
128
      return pv_get_null(msg, param, res);
1374
128
    }
1375
37
    return pv_get_strval(msg, param, res, &(get_ppi(msg)->display));
1376
165
    }
1377
1378
330
    if((uri=parse_ppi_uri(msg))==NULL) {
1379
316
    LM_ERR("cannot parse P-Preferred-Identity URI\n");
1380
316
    return pv_get_null(msg, param, res);
1381
316
    }
1382
1383
14
    if(param->pvn.u.isname.name.n==2) { /* username */
1384
7
    if(uri->user.s==NULL || uri->user.len<=0) {
1385
1
        LM_DBG("no P-Preferred-Identity username\n");
1386
1
        return pv_get_null(msg, param, res);
1387
1
    }
1388
6
    return pv_get_strval(msg, param, res, &uri->user);
1389
7
    } else if(param->pvn.u.isname.name.n==3) { /* domain */
1390
7
    if(uri->host.s==NULL || uri->host.len<=0) {
1391
2
      LM_DBG("no P-Preferred-Identity domain\n");
1392
2
      return pv_get_null(msg, param, res);
1393
2
    }
1394
5
    return pv_get_strval(msg, param, res, &uri->host);
1395
7
    }
1396
1397
0
  LM_ERR("unknown specifier\n");
1398
0
  return pv_get_null(msg, param, res);
1399
14
}
1400
1401
static int pv_get_pai(struct sip_msg *msg, pv_param_t *param,
1402
    pv_value_t *res)
1403
10.7k
{
1404
10.7k
    if(msg==NULL)
1405
0
    return -1;
1406
1407
10.7k
    if(parse_pai_header(msg)==-1)
1408
10.7k
    {
1409
10.7k
    LM_DBG("no P-Asserted-Identity header\n");
1410
10.7k
    return pv_get_null(msg, param, res);
1411
10.7k
    }
1412
1413
16
    if(msg->pai==NULL || get_pai(msg)==NULL) {
1414
0
    LM_DBG("no P-Asserted-Identity header\n");
1415
0
    return pv_get_null(msg, param, res);
1416
0
    }
1417
1418
16
  return pv_get_strval(msg, param, res, &(get_pai(msg)->uri));
1419
16
}
1420
1421
static int pv_get_dset(struct sip_msg *msg, pv_param_t *param,
1422
    pv_value_t *res)
1423
10.7k
{
1424
10.7k
  str s;
1425
1426
10.7k
  if(msg==NULL)
1427
0
    return -1;
1428
1429
10.7k
  s.s = print_dset(msg, &s.len);
1430
10.7k
  if (s.s == NULL)
1431
10.7k
    return pv_get_null(msg, param, res);
1432
0
  s.len -= CRLF_LEN;
1433
1434
0
  return pv_get_strval(msg, param, res, &s);
1435
10.7k
}
1436
1437
1438
static int pv_get_dsturi(struct sip_msg *msg, pv_param_t *param,
1439
    pv_value_t *res)
1440
21.5k
{
1441
21.5k
  if(msg==NULL)
1442
0
    return -1;
1443
1444
21.5k
  if (msg->dst_uri.s == NULL) {
1445
21.5k
    LM_DBG("no destination URI\n");
1446
21.5k
    return pv_get_null(msg, param, res);
1447
21.5k
  }
1448
1449
0
  return pv_get_strval(msg, param, res, &msg->dst_uri);
1450
21.5k
}
1451
1452
static int pv_get_dsturi_attr(struct sip_msg *msg, pv_param_t *param,
1453
    pv_value_t *res)
1454
32.3k
{
1455
32.3k
  struct sip_uri uri;
1456
32.3k
  unsigned short proto;
1457
32.3k
  str proto_s;
1458
1459
32.3k
  if(msg==NULL)
1460
0
    return -1;
1461
1462
32.3k
  if (msg->dst_uri.s == NULL) {
1463
32.3k
    LM_DBG("no destination URI\n");
1464
32.3k
    return pv_get_null(msg, param, res);
1465
32.3k
  }
1466
1467
0
  if(parse_uri(msg->dst_uri.s, msg->dst_uri.len, &uri)!=0)
1468
0
  {
1469
0
    LM_ERR("failed to parse dst uri\n");
1470
0
    return pv_get_null(msg, param, res);
1471
0
  }
1472
1473
0
  if(param->pvn.u.isname.name.n==1) /* domain */
1474
0
  {
1475
0
    if(uri.host.s==NULL || uri.host.len<=0)
1476
0
      return pv_get_null(msg, param, res);
1477
0
    return pv_get_strval(msg, param, res, &uri.host);
1478
0
  } else if(param->pvn.u.isname.name.n==2) /* port */ {
1479
0
    if(uri.port.s==NULL)
1480
0
      return pv_get_uintval(msg, param, res, get_uri_port(&uri, &proto));
1481
0
    return pv_get_strintval(msg, param, res, &uri.port, (int)uri.port_no);
1482
0
  } else if(param->pvn.u.isname.name.n==3) /* proto */ {
1483
0
    if(uri.transport_val.s==NULL) {
1484
0
      get_uri_port(&uri, &proto);
1485
0
      proto_s.s = protos[proto].name;
1486
0
      proto_s.len = proto_s.s ? strlen(proto_s.s) : 0;
1487
0
      return pv_get_strintval(msg, param, res, &proto_s, (int)proto);
1488
0
    }
1489
0
    return pv_get_strintval(msg, param, res, &uri.transport_val,
1490
0
        (int)uri.proto);
1491
0
  }
1492
1493
0
  LM_ERR("invalid specifier\n");
1494
0
  return pv_get_null(msg, param, res);
1495
0
}
1496
1497
static int pv_get_content_type(struct sip_msg *msg, pv_param_t *param,
1498
    pv_value_t *res)
1499
10.7k
{
1500
10.7k
#define BUFLEN 1024
1501
1502
10.7k
  str s;
1503
10.7k
  int idx=-1;
1504
10.7k
  int idxf=-1;
1505
10.7k
  int distance=0;
1506
10.7k
  char buf[BUFLEN];
1507
10.7k
  struct sip_msg_body* sbody;
1508
10.7k
  struct body_part* body_part;
1509
10.7k
  struct body_part* neg_index[2];
1510
1511
10.7k
  if(msg==NULL)
1512
0
    return -1;
1513
1514
10.7k
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
1515
0
    LM_ERR("invalid index\n");
1516
0
    return -1;
1517
0
  }
1518
1519
  /* no index or all contenttypes */
1520
10.7k
  if (param->pvi.type==0 || idxf == PV_IDX_ALL) {
1521
10.7k
    if(msg->content_type==NULL
1522
10.7k
        && ((parse_headers(msg, HDR_CONTENTTYPE_F, 0)==-1)
1523
10.7k
         || (msg->content_type==NULL)))
1524
10.7k
    {
1525
10.7k
      LM_DBG("no Content-Type header\n");
1526
10.7k
      return pv_get_null(msg, param, res);
1527
10.7k
    }
1528
1529
    /* only the main contenttype requested*/
1530
17
    if (param->pvi.type==0)
1531
17
      return pv_get_strval(msg, param, res, &msg->content_type->body);
1532
17
  }
1533
1534
0
  if ( parse_sip_body(msg)<0 || (sbody=msg->body)==NULL ) {
1535
0
    LM_DBG("no body found\n");
1536
0
    return pv_get_null(msg, param, res);
1537
0
  }
1538
1539
  /* one contenttype request */
1540
0
  if (idxf != PV_IDX_ALL) {
1541
0
    if (idx< 0) {
1542
0
      neg_index[0] = neg_index[1] = &sbody->first;
1543
      /*distance=last_body_postition-searched_body_position*/
1544
0
      distance -= idx+1;
1545
0
      while (neg_index[1]->next) {
1546
0
        if (distance == 0) {
1547
0
          neg_index[0] = neg_index[0]->next;
1548
0
        } else {
1549
0
          distance--;
1550
0
        }
1551
0
        neg_index[1] = neg_index[1]->next;
1552
0
      }
1553
1554
0
      if (distance>0) {
1555
0
        LM_ERR("Index too low [%d]\n", idx);
1556
0
        return pv_get_null(msg, param, res);
1557
0
      }
1558
1559
0
      s.s = convert_mime2string_CT(neg_index[0]->mime);
1560
0
      s.len = strlen(s.s);
1561
0
    } else {
1562
0
      body_part = &sbody->first;
1563
0
      distance = idx;
1564
0
      while (distance && body_part->next) {
1565
0
        distance--;
1566
0
        body_part=body_part->next;
1567
0
      }
1568
1569
0
      if (distance > 0) {
1570
0
        LM_ERR("Index too big [%d]\n", idx);
1571
0
        return pv_get_null(msg, param, res);
1572
0
      }
1573
1574
0
      s.s = convert_mime2string_CT(body_part->mime);
1575
0
      s.len = strlen(s.s);
1576
0
    }
1577
0
  } else {
1578
    /* copy main content type */
1579
0
    memcpy(buf, msg->content_type->body.s, msg->content_type->body.len);
1580
0
    buf[msg->content_type->body.len] = ',';
1581
0
    s.len = msg->content_type->body.len+1;
1582
1583
    /* copy all the other contenttypes */
1584
0
    body_part = &sbody->first;
1585
0
    while (body_part) {
1586
0
      s.s = convert_mime2string_CT(body_part->mime);
1587
0
      if (s.len + strlen(s.s) >= BUFLEN) {
1588
0
        LM_CRIT("buffer overflow! Too many contenttypes!\n");
1589
0
        return pv_get_null(msg, param, res);
1590
0
      }
1591
1592
0
      memcpy( buf+s.len, s.s, strlen(s.s));
1593
0
      s.len += strlen(s.s);
1594
1595
      /* delimiter only if something follows */
1596
0
      if(body_part->next)
1597
0
        buf[s.len++] = ',';
1598
1599
0
      body_part = body_part->next;
1600
0
    }
1601
0
    s.s = buf;
1602
0
  }
1603
1604
0
  return pv_get_strval(msg, param, res, &s);
1605
1606
0
#undef BUFLEN
1607
0
}
1608
1609
static int pv_get_content_length(struct sip_msg *msg, pv_param_t *param,
1610
    pv_value_t *res)
1611
10.7k
{
1612
10.7k
  if(msg==NULL)
1613
0
    return -1;
1614
10.7k
  if(msg->content_length==NULL
1615
10.7k
      && ((parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1)
1616
10.7k
       || (msg->content_length==NULL)))
1617
10.7k
  {
1618
10.7k
    LM_DBG("no Content-Length header\n");
1619
10.7k
    return pv_get_null(msg, param, res);
1620
10.7k
  }
1621
1622
65
  return pv_get_intstrval(msg, param, res,
1623
65
      (int)(long)msg->content_length->parsed,
1624
65
      &msg->content_length->body);
1625
10.7k
}
1626
1627
static int pv_parse_rb_name(pv_spec_p sp, const str *in)
1628
0
{
1629
0
  if(in==NULL || in->s==NULL || sp==NULL)
1630
0
    return -1;
1631
1632
0
  if (decode_mime_type( in->s, in->s+in->len ,
1633
0
  (unsigned int *)&sp->pvp.pvn.u.isname.name.n , NULL) == 0) {
1634
0
    LM_ERR("unsupported mime <%.*s>\n",in->len,in->s);
1635
0
    return -1;
1636
0
  }
1637
1638
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;  /* INT/STR for var name type */
1639
0
  sp->pvp.pvn.u.isname.type = 0;      /* name is INT */
1640
1641
0
  return 0;
1642
0
}
1643
1644
static int pv_get_msg_body(struct sip_msg *msg, pv_param_t *param,
1645
    pv_value_t *res)
1646
21.5k
{
1647
21.5k
  str s;
1648
21.5k
  int idx=-1;
1649
21.5k
  int idxf=-1;
1650
21.5k
  int distance=0;
1651
21.5k
  struct sip_msg_body* sbody;
1652
21.5k
  struct body_part* body_part;
1653
21.5k
  struct body_part* neg_index[2];
1654
21.5k
  unsigned int mime;
1655
1656
21.5k
  if(msg==NULL)
1657
0
    return -1;
1658
1659
21.5k
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
1660
0
    LM_ERR("invalid index\n");
1661
0
    return -1;
1662
0
  }
1663
1664
  /* any index specified */
1665
21.5k
  if (param->pvi.type==0 || idxf==PV_IDX_ALL) {
1666
21.5k
    if (param->pvn.u.isname.name.n==0) {
1667
      /* no name/mime -> requests all bodies */
1668
21.5k
      if (get_body( msg, &s)!=0 || s.len==0 ) {
1669
21.4k
        LM_DBG("no message body\n");
1670
21.4k
        return pv_get_null(msg, param, res);
1671
21.4k
      }
1672
92
      goto end;
1673
21.5k
    } else {
1674
      /* return first part with the requested mime */
1675
0
      idx = 0;
1676
0
    }
1677
21.5k
  }
1678
1679
0
  if ( parse_sip_body(msg)<0 || (sbody=msg->body)==NULL ) {
1680
0
    LM_DBG("no body found\n");
1681
0
    return pv_get_null(msg, param, res);
1682
0
  }
1683
1684
0
  mime = param->pvn.u.isname.name.n;
1685
0
  LM_DBG("--------mime is <%d>, idx=%d\n",mime, idx);
1686
1687
0
#define first_part_by_mime( _part_start, _part_end, _mime) \
1688
0
  do {\
1689
0
    _part_end = _part_start;\
1690
0
    while( (_part_end) && \
1691
0
    !(is_body_part_received(_part_end) && ((_mime)==0 || \
1692
0
    (_mime)==(_part_end)->mime )) ) { \
1693
0
      _part_end = (_part_end)->next; \
1694
0
    } \
1695
0
  }while(0)
1696
1697
0
  if (idx<0) {
1698
0
    first_part_by_mime( &sbody->first, neg_index[1], mime );
1699
0
    neg_index[0] = neg_index[1];
1700
1701
0
    if (neg_index[0]==NULL) {
1702
0
      LM_DBG("Body part not found for <%d>\n", mime);
1703
0
      return pv_get_null(msg, param, res);
1704
0
    }
1705
1706
    /*distance=last_body_postition-searched_body_position*/
1707
0
    distance -= idx+1;
1708
0
    first_part_by_mime(neg_index[1]->next, neg_index[1], mime);
1709
0
    while (neg_index[1]) {
1710
0
      if (distance == 0) {
1711
0
        first_part_by_mime( neg_index[0]->next, neg_index[0], mime );
1712
0
      } else {
1713
0
        distance--;
1714
0
      }
1715
0
      first_part_by_mime( neg_index[1]->next, neg_index[1], mime );
1716
0
    }
1717
1718
0
    if (distance>0) {
1719
0
      LM_DBG("Index too low [%d]\n", idx);
1720
0
      return pv_get_null(msg, param, res);
1721
0
    }
1722
1723
0
    s.s = neg_index[0]->body.s;
1724
0
    s.len = neg_index[0]->body.len;
1725
0
  } else {
1726
0
    first_part_by_mime( &sbody->first, body_part, mime );
1727
0
    distance = idx;
1728
0
    while (distance && body_part ) {
1729
0
      distance--;
1730
0
      first_part_by_mime( body_part->next, body_part, mime );
1731
0
    }
1732
1733
0
    if (distance>0 || body_part==NULL) {
1734
0
      LM_DBG("Index too big [%d], body_part=%p\n", idx,body_part);
1735
0
      return pv_get_null(msg, param, res);
1736
0
    }
1737
1738
0
    s.s = body_part->body.s;
1739
0
    s.len = body_part->body.len;
1740
0
  }
1741
1742
92
end:
1743
92
  return pv_get_strval(msg, param, res, &s);
1744
0
}
1745
1746
static int pv_get_authattr(struct sip_msg *msg, pv_param_t *param,
1747
    pv_value_t *res)
1748
140k
{
1749
140k
  struct hdr_field *hdr;
1750
140k
  str *s;
1751
1752
140k
  if(msg==NULL)
1753
0
    return -1;
1754
1755
140k
  if ((msg->REQ_METHOD==METHOD_ACK) || (msg->REQ_METHOD==METHOD_CANCEL)) {
1756
91
    LM_DBG("no [Proxy-]Authorization header\n");
1757
91
    return pv_get_null(msg, param, res);
1758
91
  }
1759
1760
140k
  if ((parse_headers(msg, HDR_PROXYAUTH_F|HDR_AUTHORIZATION_F, 0)==-1)
1761
140k
      || (msg->proxy_auth==0 && msg->authorization==0))
1762
125k
  {
1763
125k
    LM_DBG("no [Proxy-]Authorization header\n");
1764
125k
    return pv_get_null(msg, param, res);
1765
125k
  }
1766
1767
14.9k
  hdr = (msg->proxy_auth==0)?msg->authorization:msg->proxy_auth;
1768
14.9k
  if(parse_credentials(hdr)!=0) {
1769
8.00k
    LM_ERR("failed to parse credentials\n");
1770
8.00k
    return pv_get_null(msg, param, res);
1771
8.00k
  }
1772
1773
6.98k
  switch(param->pvn.u.isname.name.n)
1774
6.98k
  {
1775
537
    case 11:
1776
537
      s = &((auth_body_t*)(hdr->parsed))->digest.nc;
1777
537
      break;
1778
537
    case 10:
1779
537
      s = &((auth_body_t*)(hdr->parsed))->digest.qop.qop_str;
1780
537
      break;
1781
537
    case 9:
1782
537
      s = &((auth_body_t*)(hdr->parsed))->digest.alg.alg_str;
1783
537
      break;
1784
537
    case 8:
1785
537
      s = &((auth_body_t*)(hdr->parsed))->digest.opaque;
1786
537
      break;
1787
537
    case 7:
1788
537
      s = &((auth_body_t*)(hdr->parsed))->digest.cnonce;
1789
537
      break;
1790
537
    case 6:
1791
537
      s = &((auth_body_t*)(hdr->parsed))->digest.response;
1792
537
      break;
1793
1.07k
    case 5:
1794
1.07k
      s = &((auth_body_t*)(hdr->parsed))->digest.nonce;
1795
1.07k
      break;
1796
537
    case 4:
1797
537
      s = &((auth_body_t*)(hdr->parsed))->digest.username.domain;
1798
537
      break;
1799
537
    case 3:
1800
537
      s = &((auth_body_t*)(hdr->parsed))->digest.uri;
1801
537
      break;
1802
537
    case 2:
1803
537
      s = &((auth_body_t*)(hdr->parsed))->digest.realm;
1804
537
      break;
1805
537
    case 1:
1806
537
      s = &((auth_body_t*)(hdr->parsed))->digest.username.user;
1807
537
      break;
1808
537
    default:
1809
537
      s = &((auth_body_t*)(hdr->parsed))->digest.username.whole;
1810
6.98k
  }
1811
1812
6.98k
  if (s->len==0)
1813
6.30k
    return pv_get_null(msg, param, res);
1814
681
  return pv_get_strval(msg, param, res, s);
1815
6.98k
}
1816
1817
1818
static inline str *cred_user(struct sip_msg *rq)
1819
10.7k
{
1820
10.7k
  struct hdr_field* h;
1821
10.7k
  auth_body_t* cred;
1822
1823
10.7k
  get_authorized_cred(rq->proxy_auth, &h);
1824
10.7k
  if (!h) get_authorized_cred(rq->authorization, &h);
1825
10.7k
  if (!h) return 0;
1826
0
  cred=(auth_body_t*)(h->parsed);
1827
0
  if (!cred || !cred->digest.username.user.len)
1828
0
      return 0;
1829
0
  return &cred->digest.username.user;
1830
0
}
1831
1832
1833
static inline str *cred_realm(struct sip_msg *rq)
1834
0
{
1835
0
  str* realm;
1836
0
  struct hdr_field* h;
1837
0
  auth_body_t* cred;
1838
1839
0
  get_authorized_cred(rq->proxy_auth, &h);
1840
0
  if (!h) get_authorized_cred(rq->authorization, &h);
1841
0
  if (!h) return 0;
1842
0
  cred=(auth_body_t*)(h->parsed);
1843
0
  if (!cred) return 0;
1844
0
  realm = GET_REALM(&cred->digest);
1845
0
  if (!realm->len || !realm->s) {
1846
0
    return 0;
1847
0
  }
1848
0
  return realm;
1849
0
}
1850
1851
static int pv_get_acc_username(struct sip_msg *msg, pv_param_t *param,
1852
    pv_value_t *res)
1853
10.7k
{
1854
10.7k
  static char buf[MAX_URI_SIZE];
1855
10.7k
  str* user;
1856
10.7k
  str* realm;
1857
10.7k
  struct sip_uri puri;
1858
10.7k
  struct to_body* from;
1859
10.7k
  str s;
1860
1861
  /* try to take it from credentials */
1862
10.7k
  user = cred_user(msg);
1863
10.7k
  if (user) {
1864
0
    realm = cred_realm(msg);
1865
0
    if (realm) {
1866
0
      s.len = user->len+1+realm->len;
1867
0
      if (s.len > MAX_URI_SIZE) {
1868
0
        LM_ERR("uri too long\n");
1869
0
        return pv_get_null(msg, param, res);
1870
0
      }
1871
0
      s.s = buf;
1872
0
      memcpy(s.s, user->s, user->len);
1873
0
      (s.s)[user->len] = '@';
1874
0
      memcpy(s.s+user->len+1, realm->s, realm->len);
1875
0
      return pv_get_strval(msg, param, res, &s);
1876
0
    }
1877
0
    return pv_get_strval(msg, param, res, user);
1878
0
  }
1879
1880
  /* from from uri */
1881
10.7k
  if(parse_from_header(msg)<0)
1882
10.6k
  {
1883
10.6k
    LM_ERR("cannot parse FROM header\n");
1884
10.6k
    return pv_get_null(msg, param, res);
1885
10.6k
  }
1886
153
  if (msg->from && (from=get_from(msg)) && from->uri.len) {
1887
153
    if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) {
1888
46
      LM_ERR("bad From URI\n");
1889
46
      return pv_get_null(msg, param, res);
1890
46
    }
1891
107
    s.len = puri.user.len + 1 + puri.host.len;
1892
107
    if (s.len > MAX_URI_SIZE) {
1893
1
      LM_ERR("from URI too long\n");
1894
1
      return pv_get_null(msg, param, res);
1895
1
    }
1896
106
    s.s = buf;
1897
106
    memcpy(s.s, puri.user.s, puri.user.len);
1898
106
    (s.s)[puri.user.len] = '@';
1899
106
    memcpy(s.s + puri.user.len + 1, puri.host.s, puri.host.len);
1900
106
  } else {
1901
0
    s.len = 0;
1902
0
    s.s = 0;
1903
0
  }
1904
106
  return pv_get_strval(msg, param, res, &s);
1905
153
}
1906
1907
1908
0
#define BR_URI_S         "uri"
1909
0
#define BR_URI_LEN       (sizeof(BR_URI_S)-1)
1910
0
#define BR_URI_ID        1
1911
0
#define BR_DURI_S        "duri"
1912
0
#define BR_DURI_LEN      (sizeof(BR_DURI_S)-1)
1913
0
#define BR_DURI_ID       2
1914
0
#define BR_Q_S           "q"
1915
0
#define BR_Q_LEN         (sizeof(BR_Q_S)-1)
1916
0
#define BR_Q_ID          3
1917
0
#define BR_PATH_S        "path"
1918
0
#define BR_PATH_LEN      (sizeof(BR_PATH_S)-1)
1919
0
#define BR_PATH_ID       4
1920
0
#define BR_FLAGS_S       "flags"
1921
0
#define BR_FLAGS_LEN     (sizeof(BR_FLAGS_S)-1)
1922
0
#define BR_FLAGS_ID       5
1923
0
#define BR_SOCKET_S       "socket"
1924
0
#define BR_SOCKET_LEN     (sizeof(BR_SOCKET_S)-1)
1925
0
#define BR_SOCKET_ID      6
1926
1927
static int pv_parse_branch_name(pv_spec_p sp, const str *in)
1928
0
{
1929
0
  if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
1930
0
    return -1;
1931
1932
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
1933
0
  sp->pvp.pvn.u.isname.type = 0;
1934
1935
0
  if (in->len==BR_URI_LEN &&
1936
0
  strncasecmp(in->s, BR_URI_S, BR_URI_LEN)==0 ) {
1937
0
    sp->pvp.pvn.u.isname.name.n = BR_URI_ID;
1938
0
  } else
1939
0
  if (in->len==BR_DURI_LEN &&
1940
0
  strncasecmp(in->s, BR_DURI_S, BR_DURI_LEN)==0 ) {
1941
0
    sp->pvp.pvn.u.isname.name.n = BR_DURI_ID;
1942
0
  } else
1943
0
  if (in->len==BR_Q_LEN &&
1944
0
  strncasecmp(in->s, BR_Q_S, BR_Q_LEN)==0 ) {
1945
0
    sp->pvp.pvn.u.isname.name.n = BR_Q_ID;
1946
0
  } else
1947
0
  if (in->len==BR_PATH_LEN &&
1948
0
  strncasecmp(in->s, BR_PATH_S, BR_PATH_LEN)==0 ) {
1949
0
    sp->pvp.pvn.u.isname.name.n = BR_PATH_ID;
1950
0
  } else
1951
0
  if (in->len==BR_FLAGS_LEN &&
1952
0
  strncasecmp(in->s, BR_FLAGS_S, BR_FLAGS_LEN)==0 ) {
1953
0
    sp->pvp.pvn.u.isname.name.n = BR_FLAGS_ID;
1954
0
  } else
1955
0
  if (in->len==BR_SOCKET_LEN &&
1956
0
  strncasecmp(in->s, BR_SOCKET_S, BR_SOCKET_LEN)==0 ) {
1957
0
    sp->pvp.pvn.u.isname.name.n = BR_SOCKET_ID;
1958
0
  } else {
1959
0
    LM_ERR("unsupported BRANCH field <%.*s>\n",in->len,in->s);
1960
0
    return -1;
1961
0
  }
1962
1963
0
  return 0;
1964
0
}
1965
1966
static inline int get_branch_field( int idx, pv_name_t *pvn, pv_value_t *res)
1967
0
{
1968
0
  str uri;
1969
0
  qvalue_t q;
1970
0
  str duri;
1971
0
  str path;
1972
0
  unsigned int flags;
1973
0
  const struct socket_info *si;
1974
1975
0
  uri.s = get_branch(idx, &uri.len, &q, &duri, &path, &flags, &si);
1976
0
  if (!uri.s)
1977
0
    return pv_get_null( NULL, NULL, res);
1978
1979
  /* got a valid branch, return the field */
1980
0
  switch (pvn->u.isname.name.n) {
1981
0
    case 0:
1982
0
    case BR_URI_ID: /* return URI */
1983
0
      res->rs = uri;
1984
0
      res->flags = PV_VAL_STR;
1985
0
      break;
1986
0
    case BR_Q_ID: /* return Q */
1987
0
      res->rs.s = q2str(q, (unsigned int*)&res->rs.len);
1988
0
      res->flags = PV_VAL_STR;
1989
0
      break;
1990
0
    case BR_DURI_ID: /* return DURI */
1991
0
      if ( !duri.s || !duri.len)
1992
0
        return pv_get_null(NULL, NULL, res);
1993
0
      res->rs = duri;
1994
0
      res->flags = PV_VAL_STR;
1995
0
      break;
1996
0
    case BR_PATH_ID: /* return PATH */
1997
0
      if ( !path.s || !path.len)
1998
0
        return pv_get_null(NULL, NULL, res);
1999
0
      res->rs = path;
2000
0
      res->flags = PV_VAL_STR;
2001
0
      break;
2002
0
    case BR_FLAGS_ID: /* return FLAGS */
2003
0
      res->rs = bitmask_to_flag_list(FLAG_TYPE_BRANCH, flags);
2004
0
      res->flags = PV_VAL_STR;
2005
0
      break;
2006
0
    case BR_SOCKET_ID: /* return SOCKET */
2007
0
      if ( !si )
2008
0
        return pv_get_null(NULL, NULL, res);
2009
0
      res->rs = si->sock_str;
2010
0
      res->flags = PV_VAL_STR;
2011
0
      break;
2012
0
    default:
2013
0
      LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.name.n);
2014
0
      return pv_get_null(NULL, NULL, res);
2015
0
  }
2016
0
  return 0;
2017
0
}
2018
2019
2020
static int pv_get_branch_fields(struct sip_msg *msg, pv_param_t *param,
2021
    pv_value_t *res)
2022
21.5k
{
2023
21.5k
  int idx;
2024
21.5k
  int idxf;
2025
21.5k
  char *p;
2026
2027
21.5k
  if(msg==NULL || res==NULL)
2028
0
    return -1;
2029
2030
21.5k
  if (get_nr_branches() == 0)
2031
21.5k
    return pv_get_null(msg, param, res);
2032
2033
  /* get the index */
2034
0
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
2035
0
    LM_ERR("invalid index\n");
2036
0
    return -1;
2037
0
  }
2038
2039
0
  if (idxf!=PV_IDX_ALL && idx==0) {
2040
    /* no index specified -> return the first branch */
2041
0
    return get_branch_field( 0, &param->pvn, res);
2042
0
  }
2043
2044
0
  if(idxf==PV_IDX_ALL) {
2045
    /* return all branches */
2046
0
    p = pv_local_buf;
2047
0
    idx = 0;
2048
2049
0
    while ( idx<get_nr_branches() ) {
2050
2051
0
      get_branch_field( idx, &param->pvn, res);
2052
2053
0
      if ( pv_local_buf + PV_LOCAL_BUF_SIZE <=
2054
0
      p + res->rs.len + PV_FIELD_DELIM_LEN ) {
2055
0
        LM_ERR("local buffer length exceeded\n");
2056
0
        return pv_get_null(msg, param, res);
2057
0
      }
2058
2059
0
      if (idx) {
2060
0
        memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
2061
0
        p += PV_FIELD_DELIM_LEN;
2062
0
      }
2063
2064
0
      memcpy(p, res->rs.s, res->rs.len);
2065
0
      p += res->rs.len;
2066
0
      idx++;
2067
0
    }
2068
2069
0
    res->rs.s = pv_local_buf;
2070
0
    res->rs.len = p - pv_local_buf;
2071
0
    res->flags = PV_VAL_STR;
2072
0
    return 0;
2073
0
  }
2074
2075
  /* numerical index */
2076
0
  if (idx<0) {
2077
    /* index from the end */
2078
0
    if (-idx > get_nr_branches())
2079
0
      return pv_get_null(msg, param, res);
2080
0
    idx = get_nr_branches() + idx;
2081
0
  }
2082
2083
  /* return the request branch info */
2084
0
  return get_branch_field( idx, &param->pvn, res);
2085
0
}
2086
2087
2088
/******** LISTENING SOCKETS related vars & functions **********/
2089
2090
0
#define SOCK_IP_S             "ip"
2091
0
#define SOCK_IP_LEN           (sizeof(SOCK_IP_S)-1)
2092
0
#define SOCK_IP_ID            1
2093
0
#define SOCK_PORT_S           "port"
2094
0
#define SOCK_PORT_LEN         (sizeof(SOCK_PORT_S)-1)
2095
0
#define SOCK_PORT_ID          2
2096
0
#define SOCK_PROTO_S          "proto"
2097
0
#define SOCK_PROTO_LEN        (sizeof(SOCK_PROTO_S)-1)
2098
0
#define SOCK_PROTO_ID         3
2099
0
#define SOCK_ADV_IP_S         "advertised_ip"
2100
0
#define SOCK_ADV_IP_LEN       (sizeof(SOCK_ADV_IP_S)-1)
2101
0
#define SOCK_ADV_IP_ID        4
2102
0
#define SOCK_ADV_PORT_S       "advertised_port"
2103
0
#define SOCK_ADV_PORT_LEN     (sizeof(SOCK_ADV_PORT_S)-1)
2104
0
#define SOCK_ADV_PORT_ID      5
2105
0
#define SOCK_TAG_S            "tag"
2106
0
#define SOCK_TAG_LEN          (sizeof(SOCK_TAG_S)-1)
2107
0
#define SOCK_TAG_ID           6
2108
0
#define SOCK_ANYCAST_S        "anycast"
2109
0
#define SOCK_ANYCAST_LEN      (sizeof(SOCK_ANYCAST_S)-1)
2110
0
#define SOCK_ANYCAST_ID       7
2111
0
#define SOCK_AF_S             "af"
2112
0
#define SOCK_AF_LEN           (sizeof(SOCK_AF_S)-1)
2113
0
#define SOCK_AF_ID            8
2114
2115
static int pv_parse_socket_name(pv_spec_p sp, const str *in)
2116
0
{
2117
0
  if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
2118
0
    return -1;
2119
2120
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
2121
0
  sp->pvp.pvn.u.isname.type = 0;
2122
2123
0
  if (in->len==SOCK_IP_LEN &&
2124
0
  strncasecmp(in->s, SOCK_IP_S, SOCK_IP_LEN)==0 ) {
2125
0
    sp->pvp.pvn.u.isname.name.n = SOCK_IP_ID;
2126
0
  } else
2127
0
  if (in->len==SOCK_PORT_LEN &&
2128
0
  strncasecmp(in->s, SOCK_PORT_S, SOCK_PORT_LEN)==0 ) {
2129
0
    sp->pvp.pvn.u.isname.name.n = SOCK_PORT_ID;
2130
0
  } else
2131
0
  if (in->len==SOCK_PROTO_LEN &&
2132
0
  strncasecmp(in->s, SOCK_PROTO_S, SOCK_PROTO_LEN)==0 ) {
2133
0
    sp->pvp.pvn.u.isname.name.n = SOCK_PROTO_ID;
2134
0
  } else
2135
0
  if (in->len==SOCK_ADV_IP_LEN &&
2136
0
  strncasecmp(in->s, SOCK_ADV_IP_S, SOCK_ADV_IP_LEN)==0 ) {
2137
0
    sp->pvp.pvn.u.isname.name.n = SOCK_ADV_IP_ID;
2138
0
  } else
2139
0
  if (in->len==SOCK_ADV_PORT_LEN &&
2140
0
  strncasecmp(in->s, SOCK_ADV_PORT_S, SOCK_ADV_PORT_LEN)==0 ) {
2141
0
    sp->pvp.pvn.u.isname.name.n = SOCK_ADV_PORT_ID;
2142
0
  } else
2143
0
  if (in->len==SOCK_TAG_LEN &&
2144
0
  strncasecmp(in->s, SOCK_TAG_S, SOCK_TAG_LEN)==0 ) {
2145
0
    sp->pvp.pvn.u.isname.name.n = SOCK_TAG_ID;
2146
0
  } else
2147
0
  if (in->len==SOCK_ANYCAST_LEN &&
2148
0
  strncasecmp(in->s, SOCK_ANYCAST_S, SOCK_ANYCAST_LEN)==0 ) {
2149
0
    sp->pvp.pvn.u.isname.name.n = SOCK_ANYCAST_ID;
2150
0
  } else
2151
0
  if (in->len==SOCK_AF_LEN &&
2152
0
  strncasecmp(in->s, SOCK_AF_S, SOCK_AF_LEN)==0 ) {
2153
0
    sp->pvp.pvn.u.isname.name.n = SOCK_AF_ID;
2154
0
  } else {
2155
0
    LM_ERR("unsupported SOCKET_IN/OUT field <%.*s>\n",in->len,in->s);
2156
0
    return -1;
2157
0
  }
2158
2159
0
  return 0;
2160
0
}
2161
2162
2163
static inline int get_socket_field( const struct socket_info *si,
2164
                      pv_name_t *pvn, pv_value_t *res)
2165
43.1k
{
2166
43.1k
  if (si==NULL)
2167
43.1k
    return pv_get_null( NULL, NULL, res);
2168
2169
  /* return the field */
2170
0
  switch (pvn->u.isname.name.n) {
2171
0
    case 0: /* return full socket description */
2172
0
      res->rs = si->sock_str;
2173
0
      res->flags = PV_VAL_STR;
2174
0
      break;
2175
0
    case SOCK_IP_ID: /* return IP address */
2176
0
      res->rs = si->address_str;
2177
0
      res->flags = PV_VAL_STR;
2178
0
      break;
2179
0
    case SOCK_PORT_ID: /* return PORT */
2180
0
      res->rs = si->port_no_str;
2181
0
      res->ri = si->port_no;
2182
0
      res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
2183
0
      break;
2184
0
    case SOCK_PROTO_ID: /* return PROTOCOL */
2185
0
      if ( si->proto>=PROTO_FIRST && si->proto<PROTO_LAST &&
2186
0
      protos[si->proto].id ) {
2187
0
        res->rs.s = protos[si->proto].name;
2188
0
        res->rs.len = strlen(res->rs.s);
2189
0
        res->flags = PV_VAL_STR;
2190
0
      } else {
2191
0
        return pv_get_null( NULL, NULL, res);
2192
0
      }
2193
0
      break;
2194
0
    case SOCK_ADV_IP_ID: /* return advertised IP address */
2195
0
      if (si->adv_name_str.s) {
2196
0
        res->rs = si->adv_name_str;
2197
0
        res->flags = PV_VAL_STR;
2198
0
      } else {
2199
0
        return pv_get_null( NULL, NULL, res);
2200
0
      }
2201
0
      break;
2202
0
    case SOCK_ADV_PORT_ID: /* return advertised PORT */
2203
0
      if (si->adv_port_str.s) {
2204
0
        res->rs = si->adv_port_str;
2205
0
        res->ri = si->adv_port;
2206
0
        res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
2207
0
      } else {
2208
0
        return pv_get_null( NULL, NULL, res);
2209
0
      }
2210
0
      break;
2211
0
    case SOCK_TAG_ID: /* return internal TAG */
2212
0
      if (si->tag.s) {
2213
0
        res->rs = si->tag;
2214
0
        res->flags = PV_VAL_STR;
2215
0
      } else {
2216
0
        return pv_get_null( NULL, NULL, res);
2217
0
      }
2218
0
      break;
2219
0
    case SOCK_ANYCAST_ID: /* return ANYCAST */
2220
0
      if (si->flags&SI_IS_ANYCAST)
2221
0
        res->ri = 1;
2222
0
      else
2223
0
        res->ri = 0;
2224
0
      res->flags = PV_VAL_INT|PV_TYPE_INT;
2225
0
      break;
2226
0
    case SOCK_AF_ID:  /* returns Address Family */
2227
0
      if (si->address.af == AF_INET) {
2228
0
        res->rs.s = "INET";
2229
0
        res->rs.len = 4;
2230
0
      } else if (si->address.af == AF_INET6) {
2231
0
        res->rs.s = "INET6";
2232
0
        res->rs.len = 5;
2233
0
      } else
2234
0
        return pv_get_null( NULL, NULL, res);
2235
0
      res->flags = PV_VAL_STR;
2236
0
      break;
2237
0
    default:
2238
0
      LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.name.n);
2239
0
      return pv_get_null(NULL, NULL, res);
2240
0
  }
2241
0
  return 0;
2242
0
}
2243
2244
2245
static int pv_get_socket_in_fields(struct sip_msg *msg, pv_param_t *param,
2246
                              pv_value_t *res)
2247
21.5k
{
2248
2249
21.5k
  if(msg==NULL || res==NULL)
2250
0
    return -1;
2251
2252
21.5k
  return get_socket_field( msg->rcv.bind_address, &param->pvn, res);
2253
21.5k
}
2254
2255
2256
static int pv_get_socket_out_fields(struct sip_msg *msg, pv_param_t *param,
2257
                              pv_value_t *res)
2258
21.5k
{
2259
21.5k
  const struct socket_info *si;
2260
2261
21.5k
  if(msg==NULL || res==NULL)
2262
0
    return -1;
2263
2264
21.5k
  si = (msg->force_send_socket) ?
2265
21.5k
    msg->force_send_socket : msg->rcv.bind_address;
2266
2267
21.5k
  return get_socket_field( si, &param->pvn, res);
2268
21.5k
}
2269
2270
2271
2272
2273
/************************************************************/
2274
2275
/**
2276
 *
2277
 */
2278
static int pv_get_avp(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2279
0
{
2280
0
  unsigned short name_type;
2281
0
  int avp_name;
2282
0
  int_str avp_value;
2283
0
  struct usr_avp *avp;
2284
0
  int_str avp_value0;
2285
0
  struct usr_avp *avp0;
2286
0
  int idx;
2287
0
  int idxf;
2288
0
  char *p;
2289
0
  int n=0;
2290
2291
0
  if(msg==NULL || res==NULL || param==NULL)
2292
0
    return -1;
2293
2294
  /* get the name */
2295
0
  if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
2296
0
  {
2297
0
    LM_ERR("invalid name\n");
2298
0
    return -1;
2299
0
  }
2300
  /* get the index */
2301
0
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
2302
0
  {
2303
0
    LM_ERR("invalid index\n");
2304
0
    return -1;
2305
0
  }
2306
0
  if (idxf==PV_IDX_APPEND)
2307
0
    return pv_get_null(msg, param, res);
2308
2309
0
  if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0)
2310
0
    return pv_get_null(msg, param, res);
2311
0
  res->flags = PV_VAL_STR;
2312
2313
0
  if (idxf!=PV_IDX_ALL && idx==0)
2314
0
  {
2315
0
    if(avp->flags & AVP_VAL_STR) {
2316
0
      res->rs = avp_value.s;
2317
0
    } else if(avp->flags & AVP_VAL_NULL) {
2318
0
      res->flags |= PV_VAL_NULL;
2319
0
    } else {
2320
0
      res->rs.s = sint2str(avp_value.n, &res->rs.len);
2321
0
      res->ri = avp_value.n;
2322
0
      res->flags |= PV_VAL_INT|PV_TYPE_INT;
2323
0
    }
2324
0
    return 0;
2325
0
  }
2326
2327
  /* print the entire AVP array */
2328
0
  if(idxf==PV_IDX_ALL)
2329
0
  {
2330
0
    p = pv_local_buf;
2331
2332
    /* separately handle the first AVP */
2333
0
    if(avp->flags & AVP_VAL_STR) {
2334
0
      res->rs = avp_value.s;
2335
0
    } else if(avp->flags & AVP_VAL_NULL) {
2336
0
      memset(&res->rs, 0, sizeof res->rs);
2337
0
    } else {
2338
0
      res->rs.s = sint2str(avp_value.n, &res->rs.len);
2339
0
    }
2340
2341
0
    if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE)
2342
0
    {
2343
0
      LM_ERR("local buffer length exceeded!\n");
2344
0
      return pv_get_null(msg, param, res);
2345
0
    }
2346
0
    memcpy(p, res->rs.s, res->rs.len);
2347
0
    p += res->rs.len;
2348
2349
    /* print subsequent AVPs as [DELIM AVP]* */
2350
0
    while ((avp = search_first_avp(name_type, avp_name, &avp_value, avp)))
2351
0
    {
2352
0
      if(avp->flags & AVP_VAL_STR) {
2353
0
        res->rs = avp_value.s;
2354
0
      } else if(avp->flags & AVP_VAL_NULL) {
2355
0
        memset(&res->rs, 0, sizeof res->rs);
2356
0
      } else {
2357
0
        res->rs.s = sint2str(avp_value.n, &res->rs.len);
2358
0
      }
2359
2360
0
      if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE)
2361
0
      {
2362
0
        LM_ERR("local buffer length exceeded\n");
2363
0
        return pv_get_null(msg, param, res);
2364
0
      }
2365
0
      memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
2366
0
      p += PV_FIELD_DELIM_LEN;
2367
2368
0
      if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE)
2369
0
      {
2370
0
        LM_ERR("local buffer length exceeded!\n");
2371
0
        return pv_get_null(msg, param, res);
2372
0
      }
2373
0
      memcpy(p, res->rs.s, res->rs.len);
2374
0
      p += res->rs.len;
2375
0
    }
2376
2377
0
    *p = 0;
2378
0
    res->rs.s = pv_local_buf;
2379
0
    res->rs.len = p - pv_local_buf;
2380
0
    return 0;
2381
0
  }
2382
2383
  /* we have a numeric index */
2384
0
  if(idx<0)
2385
0
  {
2386
0
    n = 1;
2387
0
    avp0 = avp;
2388
0
    while ((avp0=search_first_avp(name_type, avp_name,
2389
0
            &avp_value0, avp0))!=0) n++;
2390
0
    idx = -idx;
2391
0
    if(idx>n)
2392
0
    {
2393
0
      LM_DBG("index out of range\n");
2394
0
      return pv_get_null(msg, param, res);
2395
0
    }
2396
0
    idx = n - idx;
2397
0
    if(idx==0)
2398
0
    {
2399
0
      if(avp->flags & AVP_VAL_STR) {
2400
0
        res->rs = avp_value.s;
2401
0
      } else if(avp->flags & AVP_VAL_NULL) {
2402
0
        res->flags |= PV_VAL_NULL;
2403
0
      } else {
2404
0
        res->rs.s = sint2str(avp_value.n, &res->rs.len);
2405
0
        res->ri = avp_value.n;
2406
0
        res->flags |= PV_VAL_INT|PV_TYPE_INT;
2407
0
      }
2408
0
      return 0;
2409
0
    }
2410
0
  }
2411
0
  n=0;
2412
0
  while(n<idx
2413
0
      && (avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0)
2414
0
    n++;
2415
2416
0
  if(avp!=0)
2417
0
  {
2418
0
    if(avp->flags & AVP_VAL_STR) {
2419
0
      res->rs = avp_value.s;
2420
0
    } else if(avp->flags & AVP_VAL_NULL) {
2421
0
      res->flags |= PV_VAL_NULL;
2422
0
    } else {
2423
0
      res->rs.s = sint2str(avp_value.n, &res->rs.len);
2424
0
      res->ri = avp_value.n;
2425
0
      res->flags |= PV_VAL_INT|PV_TYPE_INT;
2426
0
    }
2427
0
    return 0;
2428
0
  }
2429
2430
0
  LM_DBG("index out of range\n");
2431
0
  return pv_get_null(msg, param, res);
2432
0
}
2433
2434
2435
static int pv_resolve_hdr_name(const str *in, pv_value_t *tv)
2436
0
{
2437
0
  struct hdr_field hdr;
2438
0
  str s;
2439
0
  if(in->len>=PV_LOCAL_BUF_SIZE-1)
2440
0
  {
2441
0
    LM_ERR("name too long\n");
2442
0
    return -1;
2443
0
  }
2444
0
  memcpy(pv_local_buf, in->s, in->len);
2445
0
  pv_local_buf[in->len] = ':';
2446
0
  s.s = pv_local_buf;
2447
0
  s.len = in->len+1;
2448
2449
0
  if (parse_hname2(s.s, s.s + ((s.len<4)?4:s.len), &hdr)==0)
2450
0
  {
2451
0
    LM_ERR("error parsing header name [%.*s]\n", s.len, s.s);
2452
0
    return -1;
2453
0
  }
2454
0
  if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T)
2455
0
  {
2456
0
    LM_DBG("using hdr type (%d) instead of <%.*s>\n",
2457
0
      hdr.type, in->len, in->s);
2458
0
    tv->flags = 0;
2459
0
    tv->ri = hdr.type;
2460
0
  } else {
2461
0
    tv->flags = PV_VAL_STR;
2462
0
    tv->rs = *in;
2463
0
  }
2464
0
  return 0;
2465
0
}
2466
2467
static int pv_get_hdr_prolog(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res, pv_value_t* tv)
2468
0
{
2469
0
  if(msg==NULL || res==NULL || param==NULL)
2470
0
    return -1;
2471
2472
  /* get the name */
2473
0
  if(param->pvn.type == PV_NAME_PVAR)
2474
0
  {
2475
0
    if(pv_get_spec_name(msg, param, tv)!=0 || (!(tv->flags&PV_VAL_STR)))
2476
0
    {
2477
0
      LM_ERR("invalid name\n");
2478
0
      return -1;
2479
0
    }
2480
0
    if (pv_resolve_hdr_name(&tv->rs, tv) < 0)
2481
0
      return -1;
2482
0
  } else {
2483
0
    if(param->pvn.u.isname.type == AVP_NAME_STR)
2484
0
    {
2485
0
      tv->flags = PV_VAL_STR;
2486
0
      tv->rs = param->pvn.u.isname.name.s;
2487
0
    } else {
2488
0
      tv->flags = 0;
2489
0
      tv->ri = param->pvn.u.isname.name.n;
2490
0
    }
2491
0
  }
2492
  /* we need to be sure we have parsed all headers */
2493
0
  if(parse_headers(msg, HDR_EOH_F, 0)<0)
2494
0
  {
2495
0
    LM_ERR("error parsing headers\n");
2496
0
    return pv_get_null(msg, param, res);
2497
0
  }
2498
0
  return 1;
2499
0
}
2500
2501
static int pv_get_hdrcnt(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2502
0
{
2503
0
  pv_value_t tv;
2504
0
  struct hdr_field *hf;
2505
0
  unsigned int n;
2506
0
  int ret;
2507
2508
0
  if ( (ret=pv_get_hdr_prolog(msg,  param, res, &tv)) <= 0 )
2509
0
        return ret;
2510
2511
0
  n = 0;
2512
0
  if (tv.flags==0) {
2513
    /* it is a known header -> use type to find it */
2514
0
    for (hf=msg->headers; hf; hf=hf->next) {
2515
0
      if (tv.ri==hf->type)
2516
0
              ++n;
2517
0
    }
2518
0
  } else {
2519
    /* it is an un-known header -> use name to find it */
2520
0
    for (hf=msg->headers; hf; hf=hf->next) {
2521
0
      if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
2522
0
      && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
2523
0
        ++n;
2524
0
    }
2525
0
  }
2526
0
  return pv_get_uintval(msg, param, res, n);
2527
0
}
2528
2529
static int pv_get_hdr(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2530
0
{
2531
0
  int idx;
2532
0
  int idxf;
2533
0
  pv_value_t tv;
2534
0
  struct hdr_field *hf;
2535
0
  struct hdr_field *hf0;
2536
0
  char *p;
2537
0
  int n;
2538
0
  int ret;
2539
2540
0
  if ( (ret=pv_get_hdr_prolog(msg,  param, res, &tv)) <= 0 )
2541
0
        return ret;
2542
2543
0
  if (tv.flags==0) {
2544
    /* it is a known header -> use type to find it */
2545
0
    for (hf=msg->headers; hf; hf=hf->next) {
2546
0
      if (tv.ri==hf->type)
2547
0
        break;
2548
0
    }
2549
0
  } else {
2550
    /* it is an un-known header -> use name to find it */
2551
0
    for (hf=msg->headers; hf; hf=hf->next) {
2552
0
      if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
2553
0
      && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
2554
0
        break;
2555
0
    }
2556
0
  }
2557
2558
0
  if(hf==NULL)
2559
0
    return pv_get_null(msg, param, res);
2560
  /* get the index */
2561
0
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
2562
0
  {
2563
0
    LM_ERR("invalid index\n");
2564
0
    return -1;
2565
0
  }
2566
2567
  /* get the value */
2568
0
  res->flags = PV_VAL_STR;
2569
0
  if(idxf!=PV_IDX_ALL && idx==0)
2570
0
  {
2571
0
    res->rs  = hf->body;
2572
0
    return 0;
2573
0
  }
2574
0
  if(idxf==PV_IDX_ALL)
2575
0
  {
2576
0
    p = pv_local_buf;
2577
0
    do {
2578
0
      if(p!=pv_local_buf)
2579
0
      {
2580
0
        if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE)
2581
0
        {
2582
0
          LM_ERR("local buffer length exceeded\n");
2583
0
          return pv_get_null(msg, param, res);
2584
0
        }
2585
0
        memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
2586
0
        p += PV_FIELD_DELIM_LEN;
2587
0
      }
2588
2589
0
      if(p-pv_local_buf+hf->body.len+1>PV_LOCAL_BUF_SIZE)
2590
0
      {
2591
0
        LM_ERR("local buffer length exceeded!\n");
2592
0
        return pv_get_null(msg, param, res);
2593
0
      }
2594
0
      memcpy(p, hf->body.s, hf->body.len);
2595
0
      p += hf->body.len;
2596
      /* next hf */
2597
0
      if (tv.flags==0) {
2598
        /* it is a known header -> use type to find it */
2599
0
        for (hf=hf->next ; hf; hf=hf->next) {
2600
0
          if (tv.ri==hf->type)
2601
0
            break;
2602
0
        }
2603
0
      } else {
2604
        /* it is an un-known header -> use name to find it */
2605
0
        for (hf=hf->next ; hf; hf=hf->next) {
2606
0
          if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
2607
0
          && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
2608
0
            break;
2609
0
        }
2610
0
      }
2611
0
    } while (hf);
2612
0
    *p = 0;
2613
0
    res->rs.s = pv_local_buf;
2614
0
    res->rs.len = p - pv_local_buf;
2615
0
    return 0;
2616
0
  }
2617
2618
  /* we have a numeric index */
2619
0
  hf0 = 0;
2620
0
  if(idx<0)
2621
0
  {
2622
0
    n = 1;
2623
    /* count headers */
2624
0
    if (tv.flags==0 ) {
2625
      /* it is a known header -> use type to find it */
2626
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2627
0
        if (tv.ri==hf0->type)
2628
0
          n++;
2629
0
      }
2630
0
    } else {
2631
      /* it is an un-known header -> use name to find it */
2632
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2633
0
        if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len
2634
0
        && strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0)
2635
0
          n++;
2636
0
      }
2637
0
    }
2638
2639
0
    idx = -idx;
2640
0
    if(idx>n)
2641
0
    {
2642
0
      LM_DBG("index out of range\n");
2643
0
      return pv_get_null(msg, param, res);
2644
0
    }
2645
0
    idx = n - idx;
2646
0
    if(idx==0)
2647
0
    {
2648
0
      res->rs  = hf->body;
2649
0
      return 0;
2650
0
    }
2651
0
  }
2652
0
  n=0;
2653
0
  while(n<idx)
2654
0
  {
2655
0
    if (tv.flags==0) {
2656
      /* it is a known header -> use type to find it */
2657
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2658
0
        if (tv.ri==hf0->type) {
2659
0
          n++;
2660
0
          if(n==idx) break;
2661
0
        }
2662
0
      }
2663
0
    } else {
2664
      /* it is an un-known header -> use name to find it */
2665
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2666
0
        if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len
2667
0
        && strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0) {
2668
0
          n++;
2669
0
          if(n==idx) break;
2670
0
        }
2671
0
      }
2672
0
    }
2673
0
    if(hf0==NULL)
2674
0
      break;
2675
0
  }
2676
2677
0
  if(hf0!=0)
2678
0
  {
2679
0
    res->rs  = hf0->body;
2680
0
    return 0;
2681
0
  }
2682
2683
0
  LM_DBG("index out of range\n");
2684
0
  return pv_get_null(msg, param, res);
2685
2686
0
}
2687
2688
static int pv_get_hdr_name(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2689
10.7k
{
2690
10.7k
  int idx, idx_f;
2691
10.7k
  struct hdr_field *hf;
2692
10.7k
  char *p;
2693
10.7k
  int n;
2694
2695
10.7k
  if(msg==NULL || res==NULL || param==NULL)
2696
0
    return -1;
2697
2698
  /* get the index */
2699
10.7k
  if (pv_get_spec_index(msg, param, &idx, &idx_f) != 0) {
2700
0
    LM_ERR("invalid index\n");
2701
0
    return -1;
2702
0
  }
2703
2704
  /* make sure we have parsed all the headers */
2705
10.7k
  if (parse_headers(msg, HDR_EOH_F, 0) <0 ) {
2706
0
    LM_ERR("error parsing headers\n");
2707
0
    return pv_get_null(msg, param, res);
2708
0
  }
2709
2710
10.7k
  res->flags = PV_VAL_STR;
2711
2712
10.7k
  if (idx_f == PV_IDX_ALL) {
2713
    /* return all header names, separated by ',' */
2714
2715
0
    p = pv_local_buf;
2716
0
    hf = msg->headers;
2717
0
    do {
2718
0
      if (p != pv_local_buf) {
2719
0
        if (p - pv_local_buf + PV_FIELD_DELIM_LEN + 1 > PV_LOCAL_BUF_SIZE) {
2720
0
          LM_ERR("local buffer length exceeded\n");
2721
0
          return pv_get_null(msg, param, res);
2722
0
        }
2723
0
        memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
2724
0
        p += PV_FIELD_DELIM_LEN;
2725
0
      }
2726
2727
0
      if (p - pv_local_buf + hf->name.len + 1 > PV_LOCAL_BUF_SIZE) {
2728
0
        LM_ERR("local buffer length exceeded!\n");
2729
0
        return pv_get_null(msg, param, res);
2730
0
      }
2731
0
      memcpy(p, hf->name.s, hf->name.len);
2732
0
      p += hf->name.len;
2733
2734
0
      hf = hf->next;
2735
0
    } while (hf);
2736
2737
0
    *p = 0;
2738
0
    res->rs.s = pv_local_buf;
2739
0
    res->rs.len = p - pv_local_buf;
2740
0
    return 0;
2741
0
  }
2742
2743
10.7k
  if (idx < 0) {
2744
    /* negative index, translate it to a positive one */
2745
2746
0
    n = 0;
2747
0
    for (hf = msg->headers; hf; hf = hf->next, n++) ;
2748
0
    idx = -idx;
2749
0
    if(idx > n) {
2750
0
      LM_DBG("index [%d] out of range\n", -idx);
2751
0
      return pv_get_null(msg, param, res);
2752
0
    }
2753
0
    idx = n - idx;
2754
0
  }
2755
2756
10.7k
  for (hf = msg->headers, n = 0; hf && n != idx; hf = hf->next, n++) ;
2757
2758
10.7k
  if (!hf) {
2759
0
    LM_DBG("index [%d] out of range\n", idx);
2760
0
    return pv_get_null(msg, param, res);
2761
0
  }
2762
2763
10.7k
  res->rs = hf->name;
2764
10.7k
  return 0;
2765
10.7k
}
2766
2767
static int pv_get_scriptvar(struct sip_msg *msg,  pv_param_t *param,
2768
    pv_value_t *res)
2769
0
{
2770
0
  int ival = 0;
2771
0
  char *sval = NULL;
2772
0
  script_var_t *sv=NULL;
2773
2774
0
  if(msg==NULL || res==NULL)
2775
0
    return -1;
2776
2777
0
  if(param==NULL || param->pvn.u.dname==0)
2778
0
    return pv_get_null(msg, param, res);
2779
2780
0
  sv= (script_var_t*)param->pvn.u.dname;
2781
2782
0
  if (sv->v.flags&VAR_VAL_NULL)
2783
0
    return pv_get_null(msg, param, res);
2784
2785
0
  if(sv->v.flags&VAR_VAL_STR)
2786
0
  {
2787
0
    res->rs = sv->v.value.s;
2788
0
    res->flags = PV_VAL_STR;
2789
0
  } else {
2790
0
    sval = sint2str(sv->v.value.n, &ival);
2791
2792
0
    res->rs.s = sval;
2793
0
    res->rs.len = ival;
2794
2795
0
    res->ri = sv->v.value.n;
2796
0
    res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
2797
0
  }
2798
0
  return 0;
2799
0
}
2800
2801
/********* end PV get functions *********/
2802
2803
/********* start PV set functions *********/
2804
static int pv_set_avp(struct sip_msg* msg, pv_param_t *param,
2805
    int op, pv_value_t *val)
2806
0
{
2807
0
  int avp_name;
2808
0
  int_str avp_val;
2809
0
  int flags;
2810
0
  unsigned short name_type;
2811
0
  int idx, idxf;
2812
2813
0
  if(param==NULL)
2814
0
  {
2815
0
    LM_ERR("bad parameters\n");
2816
0
    return -1;
2817
0
  }
2818
2819
0
  if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
2820
0
  {
2821
0
    LM_ALERT("BUG in getting dst AVP name\n");
2822
0
    goto error;
2823
0
  }
2824
2825
  /* get the index */
2826
0
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
2827
0
  {
2828
0
    LM_ERR("invalid index\n");
2829
0
    return -1;
2830
0
  }
2831
2832
0
  if(val == NULL)
2833
0
  {
2834
0
    if(op == COLONEQ_T || idxf == PV_IDX_ALL)
2835
0
      destroy_avps(name_type, avp_name, 1);
2836
0
    else
2837
0
    {
2838
0
      destroy_index_avp(name_type, avp_name, idx);
2839
0
    }
2840
0
    return 0;
2841
0
  }
2842
2843
0
  if(op == COLONEQ_T || idxf == PV_IDX_ALL)
2844
0
    destroy_avps(name_type, avp_name, 1);
2845
2846
0
  flags = name_type;
2847
0
  if(val->flags&PV_TYPE_INT)
2848
0
  {
2849
0
    avp_val.n = val->ri;
2850
0
  } else {
2851
0
    avp_val.s = val->rs;
2852
0
    flags |= AVP_VAL_STR;
2853
0
  }
2854
2855
0
  if(idxf == PV_IDX_INT || idxf == PV_IDX_PVAR) /* if the avp is indexed */
2856
0
  {
2857
0
    if(replace_avp(flags, avp_name, avp_val, idx)< 0)
2858
0
    {
2859
0
      LM_ERR("Failed to replace avp\n");
2860
0
      goto error;
2861
0
    }
2862
0
  }
2863
0
  else if (idxf == PV_IDX_APPEND) /* add AVP at the end */
2864
0
  {
2865
0
    if (add_avp_last(flags, avp_name, avp_val)<0)
2866
0
    {
2867
0
      LM_ERR("error - cannot add AVP\n");
2868
0
      goto error;
2869
0
    }
2870
0
  }
2871
0
  else {
2872
0
    if (add_avp(flags, avp_name, avp_val)<0)
2873
0
    {
2874
0
      LM_ERR("error - cannot add AVP\n");
2875
0
      goto error;
2876
0
    }
2877
0
  }
2878
2879
0
  return 0;
2880
0
error:
2881
0
  return -1;
2882
0
}
2883
2884
static int pv_set_scriptvar(struct sip_msg* msg, pv_param_t *param,
2885
    int op, pv_value_t *val)
2886
0
{
2887
0
  int_str avp_val;
2888
0
  int flags;
2889
2890
0
  if(param==NULL)
2891
0
  {
2892
0
    LM_ERR("bad parameters\n");
2893
0
    return -1;
2894
0
  }
2895
2896
0
  if(param->pvn.u.dname==0)
2897
0
  {
2898
0
    LM_ERR("error - cannot find svar\n");
2899
0
    goto error;
2900
0
  }
2901
0
  if(val == NULL)
2902
0
  {
2903
0
    set_var_value((script_var_t*)param->pvn.u.dname, NULL, VAR_VAL_NULL);
2904
0
    return 0;
2905
0
  }
2906
0
  if(val->flags&PV_TYPE_INT)
2907
0
  {
2908
0
    avp_val.n = val->ri;
2909
0
    flags = 0;
2910
0
  } else {
2911
0
    avp_val.s = val->rs;
2912
0
    flags = VAR_VAL_STR;
2913
0
  }
2914
0
  if(set_var_value((script_var_t*)param->pvn.u.dname, &avp_val, flags)==NULL)
2915
0
  {
2916
0
    LM_ERR("error - cannot set svar [%.*s] \n",
2917
0
        ((script_var_t*)param->pvn.u.dname)->name.len,
2918
0
        ((script_var_t*)param->pvn.u.dname)->name.s);
2919
0
    goto error;
2920
0
  }
2921
0
  return 0;
2922
0
error:
2923
0
  return -1;
2924
0
}
2925
2926
static int pv_set_dsturi(struct sip_msg* msg, pv_param_t *param,
2927
    int op, pv_value_t *val)
2928
0
{
2929
0
  if(msg==NULL || param==NULL)
2930
0
  {
2931
0
    LM_ERR("bad parameters\n");
2932
0
    return -1;
2933
0
  }
2934
2935
0
  if(val == NULL)
2936
0
  {
2937
0
    reset_dst_uri(msg);
2938
2939
0
    return 1;
2940
0
  }
2941
0
  if(!(val->flags&PV_VAL_STR))
2942
0
  {
2943
0
    LM_ERR("error - str value required to set dst uri\n");
2944
0
    goto error;
2945
0
  }
2946
2947
0
  if(set_dst_uri(msg, &val->rs)!=0)
2948
0
    goto error;
2949
2950
0
  return 0;
2951
0
error:
2952
0
  return -1;
2953
0
}
2954
2955
static int pv_set_ruri(struct sip_msg* msg, pv_param_t *param,
2956
    int op, pv_value_t *val)
2957
0
{
2958
0
  if(msg==NULL || param==NULL || val==NULL)
2959
0
  {
2960
0
    LM_ERR("bad parameters\n");
2961
0
    return -1;
2962
0
  }
2963
2964
0
  if(!(val->flags&PV_VAL_STR))
2965
0
  {
2966
0
    LM_ERR("str value required to set R-URI\n");
2967
0
    goto error;
2968
0
  }
2969
2970
0
  if (set_ruri( msg, &val->rs)!=0) {
2971
0
    LM_ERR("failed to set RURI\n");
2972
0
    goto error;
2973
0
  }
2974
2975
0
  return 0;
2976
0
error:
2977
0
  return -1;
2978
0
}
2979
2980
static int pv_set_ru_q(struct sip_msg* msg, pv_param_t *param,
2981
    int op, pv_value_t *val)
2982
0
{
2983
0
  if(msg==NULL || param==NULL || val==NULL)
2984
0
  {
2985
0
    LM_ERR("bad parameters\n");
2986
0
    return -1;
2987
0
  }
2988
2989
0
  if(!(val->flags&PV_VAL_INT))
2990
0
  {
2991
0
    LM_ERR("int value required to set r-uri queue value\n");
2992
0
    return -1;
2993
0
  }
2994
2995
0
  if (val->ri > 1000) {
2996
0
    LM_WARN("queue value too big %d - setting queue to "
2997
0
        "maximum value (1000)\n", val->ri);
2998
0
    set_ruri_q(msg, 1000);
2999
0
  } else
3000
0
    set_ruri_q(msg, val->ri);
3001
3002
0
  return 0;
3003
0
}
3004
3005
static int pv_set_ruri_user(struct sip_msg* msg, pv_param_t *param,
3006
    int op, pv_value_t *val)
3007
0
{
3008
0
  str sval;
3009
3010
0
  if(msg==NULL || param==NULL)
3011
0
  {
3012
0
    LM_ERR("bad parameters\n");
3013
0
    return -1;
3014
0
  }
3015
3016
0
  if(val == NULL)
3017
0
    sval = str_empty;
3018
0
  else if(!(val->flags&PV_VAL_STR)) {
3019
0
    LM_ERR("str value required to set R-URI user\n");
3020
0
    return -1;
3021
0
  } else
3022
0
    sval = val->rs;
3023
3024
0
  if (rewrite_ruri(msg, &sval, 0, RW_RURI_USER) < 0) {
3025
0
    LM_ERR("Failed to set R-URI user\n");
3026
0
    return -1;
3027
0
  }
3028
3029
0
  return 0;
3030
0
}
3031
3032
static int pv_set_ruri_host(struct sip_msg* msg, pv_param_t *param,
3033
    int op, pv_value_t *val)
3034
0
{
3035
0
  if(msg==NULL || param==NULL || val==NULL)
3036
0
  {
3037
0
    LM_ERR("bad parameters\n");
3038
0
    return -1;
3039
0
  }
3040
3041
0
  if(!(val->flags&PV_VAL_STR))
3042
0
  {
3043
0
    LM_ERR("str value required to set R-URI hostname\n");
3044
0
    return -1;
3045
0
  }
3046
3047
0
  if (rewrite_ruri(msg, &val->rs, 0, RW_RURI_HOST) < 0) {
3048
0
    LM_ERR("Failed to set R-URI hostname\n");
3049
0
    return -1;
3050
0
  }
3051
3052
0
  return 0;
3053
0
}
3054
3055
static int pv_set_dsturi_host(struct sip_msg* msg, pv_param_t *param,
3056
    int op, pv_value_t *val)
3057
0
{
3058
0
  if(msg==NULL || param==NULL || val==NULL)
3059
0
  {
3060
0
    LM_ERR("bad parameters\n");
3061
0
    return -1;
3062
0
  }
3063
3064
0
  if(!(val->flags&PV_VAL_STR))
3065
0
  {
3066
0
    LM_ERR("str value required to set DST-URI hostname\n");
3067
0
    return -1;
3068
0
  }
3069
3070
0
  if (set_dst_host_port(msg, &val->rs, NULL) < 0) {
3071
0
    LM_ERR("Failed to set DST-URI host\n");
3072
0
    return -1;
3073
0
  }
3074
3075
0
  return 0;
3076
0
}
3077
3078
static int pv_set_dsturi_port(struct sip_msg* msg, pv_param_t *param,
3079
    int op, pv_value_t *val)
3080
0
{
3081
0
  str sval;
3082
3083
0
  if(msg==NULL || param==NULL)
3084
0
  {
3085
0
    LM_ERR("bad parameters\n");
3086
0
    return -1;
3087
0
  }
3088
3089
0
  if(val == NULL)
3090
0
    sval = str_empty;
3091
0
  else if(!(val->flags&PV_VAL_STR))
3092
0
    sval.s = int2str(val->ri, &sval.len);
3093
0
  else
3094
0
    sval = val->rs;
3095
3096
0
  if (set_dst_host_port(msg, NULL, &sval) < 0) {
3097
0
    LM_ERR("Failed to set DST-URI port\n");
3098
0
    return -1;
3099
0
  }
3100
3101
0
  return 0;
3102
0
}
3103
3104
3105
3106
3107
static int pv_set_ruri_port(struct sip_msg* msg, pv_param_t *param,
3108
    int op, pv_value_t *val)
3109
0
{
3110
0
  str sval;
3111
3112
0
  if(msg==NULL || param==NULL)
3113
0
  {
3114
0
    LM_ERR("bad parameters\n");
3115
0
    return -1;
3116
0
  }
3117
3118
0
  if(val == NULL)
3119
0
    sval = str_empty;
3120
0
  else if(!(val->flags&PV_VAL_STR))
3121
0
    sval.s = int2str(val->ri, &sval.len);
3122
0
  else
3123
0
    sval = val->rs;
3124
3125
0
  if (rewrite_ruri(msg, &sval, 0, RW_RURI_PORT) < 0) {
3126
0
    LM_ERR("Failed to set R-URI hostname\n");
3127
0
    return -1;
3128
0
  }
3129
3130
0
  return 0;
3131
0
}
3132
3133
3134
static int pv_set_branch(struct sip_msg* msg, pv_param_t *param,
3135
    int op, pv_value_t *val)
3136
0
{
3137
0
  if (msg==NULL || param==NULL) {
3138
0
    LM_ERR("bad parameters\n");
3139
0
    return -1;
3140
0
  }
3141
3142
0
  if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) ||
3143
0
  val->rs.len==0 ) {
3144
0
    LM_ERR("str value required to create a new branch\n");
3145
0
    return -1;
3146
0
  }
3147
3148
0
  if (append_branch( msg, &val->rs, NULL, NULL, Q_UNSPECIFIED,  0, NULL)!=1){
3149
0
    LM_ERR("failed to append new branch\n");
3150
0
    return -1;
3151
0
  }
3152
3153
0
  return 0;
3154
0
}
3155
3156
3157
static int pv_set_branch_fields(struct sip_msg* msg, pv_param_t *param,
3158
    int op, pv_value_t *val)
3159
0
{
3160
0
  int idx;
3161
0
  int idxf;
3162
0
  str *s;
3163
0
  qvalue_t q;
3164
0
  unsigned int flags;
3165
0
  const struct socket_info *si;
3166
3167
0
  if (msg==NULL || param==NULL) {
3168
0
    LM_ERR("bad parameters\n");
3169
0
    return -1;
3170
0
  }
3171
3172
0
  if (msg->first_line.type == SIP_REPLY)
3173
0
    return -1;
3174
3175
  /* get the index */
3176
0
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
3177
0
    LM_ERR("invalid index\n");
3178
0
    return -1;
3179
0
  }
3180
3181
0
  if(idxf==PV_IDX_ALL) {
3182
0
    LM_ERR("SCRIPT BUG - * not allowed in branch assignment\n");
3183
0
    return -1;
3184
0
  }
3185
3186
0
  if (idx<0) {
3187
0
    idx = get_nr_branches() + idx;
3188
0
  }
3189
3190
0
  if (idx<0 || idx>=get_nr_branches()) {
3191
0
    LM_ERR("SCRIPT BUG - inexisting branch assignment [%d/%d]\n",
3192
0
      get_nr_branches(), idx);
3193
0
    return -1;
3194
0
  }
3195
3196
0
  switch (param->pvn.u.isname.name.n) {
3197
0
    case BR_URI_ID: /* set URI */
3198
0
      if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) ||
3199
0
      val->rs.len==0 ) {
3200
0
        LM_ERR("str value required to set the branch URI\n");
3201
0
        return -1;
3202
0
      }
3203
0
      s = &val->rs;
3204
0
      return update_branch( idx, &s, NULL,
3205
0
        NULL, NULL, NULL, NULL);
3206
0
    case BR_Q_ID: /* set Q */
3207
0
      if ( val && !(val->flags&PV_VAL_INT) ) {
3208
0
        LM_ERR("INT value required to set the branch Q\n");
3209
0
        return -1;
3210
0
      }
3211
0
      q = (!val||val->flags&PV_VAL_NULL)? Q_UNSPECIFIED : val->ri;
3212
0
      return update_branch( idx, NULL, NULL,
3213
0
        NULL, &q, NULL, NULL);
3214
0
    case BR_DURI_ID: /* set DURI */
3215
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3216
0
        LM_ERR("STR value required to set the branch DURI\n");
3217
0
        return -1;
3218
0
      }
3219
0
      s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs;
3220
0
      return update_branch( idx, NULL, &s,
3221
0
        NULL, NULL, NULL, NULL);
3222
0
    case BR_PATH_ID: /* set PATH */
3223
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3224
0
        LM_ERR("STR value required to set the branch PATH\n");
3225
0
        return -1;
3226
0
      }
3227
0
      s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs;
3228
0
      return update_branch( idx, NULL, NULL,
3229
0
        &s, NULL, NULL, NULL);
3230
0
    case BR_FLAGS_ID: /* set FLAGS */
3231
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3232
0
        LM_ERR("string value required to set the branch FLAGS\n");
3233
0
        return -1;
3234
0
      }
3235
0
      flags = (!val||val->flags&PV_VAL_NULL)?
3236
0
        0 : flag_list_to_bitmask(str2const(&val->rs), FLAG_TYPE_BRANCH, FLAG_DELIM, 0);
3237
0
      return update_branch( idx, NULL, NULL,
3238
0
        NULL, NULL, &flags, NULL);
3239
0
    case BR_SOCKET_ID: /* set SOCKET */
3240
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3241
0
        LM_ERR("STR value required to set the branch SOCKET\n");
3242
0
        return -1;
3243
0
      }
3244
0
      if (!val || val->flags&PV_VAL_NULL) {
3245
0
        si = NULL;
3246
0
      } else {
3247
0
        si = parse_sock_info(&val->rs);
3248
0
        if (si==NULL)
3249
0
          return -1;
3250
0
      }
3251
0
      return update_branch( idx, NULL, NULL,
3252
0
        NULL, NULL, NULL, &si);
3253
0
    default:
3254
0
      LM_CRIT("BUG - unsupported ID %d\n",param->pvn.u.isname.type);
3255
0
      return -1;
3256
0
  }
3257
0
}
3258
3259
static int pv_set_force_sock(struct sip_msg* msg, pv_param_t *param,
3260
    int op, pv_value_t *val)
3261
0
{
3262
0
  const struct socket_info *si;
3263
3264
0
  if(msg==NULL || param==NULL)
3265
0
  {
3266
0
    LM_ERR("bad parameters\n");
3267
0
    return -1;
3268
0
  }
3269
3270
0
  if(val==NULL)
3271
0
  {
3272
0
    msg->force_send_socket = NULL;
3273
0
    return 0;
3274
0
  }
3275
3276
0
  if(!(val->flags&PV_VAL_STR) || val->rs.len<=0)
3277
0
  {
3278
0
    LM_ERR("str value required to set the force send sock\n");
3279
0
    goto error;
3280
0
  }
3281
3282
0
  si = parse_sock_info(&val->rs);
3283
0
  if (si!=NULL)
3284
0
  {
3285
0
    msg->force_send_socket = si;
3286
0
  } else {
3287
0
    LM_WARN("no socket found to match [%.*s]\n",
3288
0
        val->rs.len, val->rs.s);
3289
0
  }
3290
3291
0
  return 0;
3292
0
error:
3293
0
  return -1;
3294
0
}
3295
3296
3297
/********* end PV set functions *********/
3298
3299
static int pv_parse_scriptvar_name(pv_spec_p sp, const str *in)
3300
0
{
3301
0
  if(in==NULL || in->s==NULL || sp==NULL)
3302
0
    return -1;
3303
3304
0
  sp->pvp.pvn.type = PV_NAME_PVAR;
3305
0
  sp->pvp.pvn.u.dname = (void*)add_var(in);
3306
0
  if(sp->pvp.pvn.u.dname==NULL)
3307
0
  {
3308
0
    LM_ERR("cannot register var [%.*s]\n", in->len, in->s);
3309
0
    return -1;
3310
0
  }
3311
0
  return 0;
3312
0
}
3313
3314
static int pv_parse_hdr_name(pv_spec_p sp, const str *in)
3315
0
{
3316
0
  char *p;
3317
0
  pv_spec_p nsp = 0;
3318
0
  pv_value_t tv;
3319
3320
0
  if(in==NULL || in->s==NULL || sp==NULL)
3321
0
    return -1;
3322
3323
0
  p = in->s;
3324
0
  if(*p==PV_MARKER)
3325
0
  {
3326
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
3327
0
    if(nsp==NULL)
3328
0
    {
3329
0
      LM_ERR("no more memory\n");
3330
0
      return -1;
3331
0
    }
3332
0
    p = pv_parse_spec(in, nsp);
3333
0
    if(p==NULL)
3334
0
    {
3335
0
      LM_ERR("invalid name [%.*s]\n", in->len, in->s);
3336
0
      pv_spec_free(nsp);
3337
0
      return -1;
3338
0
    }
3339
    //LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
3340
    //pv_print_spec(nsp);
3341
0
    sp->pvp.pvn.type = PV_NAME_PVAR;
3342
0
    sp->pvp.pvn.u.dname = (void*)nsp;
3343
0
    return 0;
3344
0
  }
3345
3346
0
  if (pv_resolve_hdr_name(in, &tv) < 0)
3347
0
    return -1;
3348
3349
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3350
0
  if (!tv.flags)
3351
0
  {
3352
0
    LM_DBG("using hdr type (%d) instead of <%.*s>\n",
3353
0
      tv.ri, in->len, in->s);
3354
0
    sp->pvp.pvn.u.isname.type = 0;
3355
0
    sp->pvp.pvn.u.isname.name.n = tv.ri;
3356
0
  } else {
3357
0
    sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
3358
0
    sp->pvp.pvn.u.isname.name.s = *in;
3359
0
  }
3360
0
  return 0;
3361
0
}
3362
3363
int pv_parse_avp_name(pv_spec_p sp, const str *in)
3364
0
{
3365
0
  char *p;
3366
0
  char *s;
3367
0
  pv_spec_p nsp = 0;
3368
3369
0
  if(in==NULL || in->s==NULL || sp==NULL)
3370
0
    return -1;
3371
0
  p = in->s;
3372
0
  if(*p==PV_MARKER)
3373
0
  {
3374
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
3375
0
    if(nsp==NULL)
3376
0
    {
3377
0
      LM_ERR("no more memory\n");
3378
0
      return -1;
3379
0
    }
3380
0
    s = pv_parse_spec(in, nsp);
3381
0
    if(s==NULL)
3382
0
    {
3383
0
      LM_ERR("invalid name [%.*s]\n", in->len, in->s);
3384
0
      pv_spec_free(nsp);
3385
0
      return -1;
3386
0
    }
3387
    //LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
3388
    //pv_print_spec(nsp);
3389
0
    sp->pvp.pvn.type = PV_NAME_PVAR;
3390
0
    sp->pvp.pvn.u.dname = (void*)nsp;
3391
0
    return 0;
3392
0
  }
3393
  /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
3394
  /* always an int type from now */
3395
0
  sp->pvp.pvn.u.isname.type = 0;
3396
0
  if(parse_avp_spec(in, &sp->pvp.pvn.u.isname.name.n)!=0)
3397
0
  {
3398
0
    LM_ERR("bad avp name [%.*s]\n", in->len, in->s);
3399
0
    return -1;
3400
0
  }
3401
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3402
0
  return 0;
3403
0
}
3404
3405
static int pv_parse_avp_index(pv_spec_p sp, const str *in)
3406
0
{
3407
0
  #define AVP_APPEND_IDX "append"
3408
3409
0
  if(in==NULL || in->s==NULL || sp==NULL)
3410
0
    return -1;
3411
3412
0
  if ( (in->len==(sizeof(AVP_APPEND_IDX)-1)) &&
3413
0
  strncasecmp(in->s,AVP_APPEND_IDX,in->len)==0) {
3414
0
    sp->pvp.pvi.type = PV_IDX_APPEND;
3415
0
    return 0;
3416
0
  }
3417
0
  return pv_parse_index(sp,in);
3418
0
}
3419
3420
int pv_parse_index(pv_spec_p sp, const str *in)
3421
0
{
3422
0
  char *p;
3423
0
  char *s;
3424
0
  int sign;
3425
0
  pv_spec_p nsp = 0;
3426
3427
0
  if(in==NULL || in->s==NULL || sp==NULL)
3428
0
    return -1;
3429
0
  p = in->s;
3430
0
  if(*p==PV_MARKER)
3431
0
  {
3432
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
3433
0
    if(nsp==NULL)
3434
0
    {
3435
0
      LM_ERR("no more memory\n");
3436
0
      return -1;
3437
0
    }
3438
0
    memset(nsp, 0, sizeof(pv_spec_t));
3439
0
    s = pv_parse_spec(in, nsp);
3440
0
    if(s==NULL)
3441
0
    {
3442
0
      LM_ERR("invalid index [%.*s]\n", in->len, in->s);
3443
0
      pv_spec_free(nsp);
3444
0
      return -1;
3445
0
    }
3446
0
    sp->pvp.pvi.type = PV_IDX_PVAR;
3447
0
    sp->pvp.pvi.u.dval = (void*)nsp;
3448
0
    return 0;
3449
0
  }
3450
0
  if(*p=='*' && in->len==1)
3451
0
  {
3452
0
    sp->pvp.pvi.type = PV_IDX_ALL;
3453
0
    return 0;
3454
0
  }
3455
0
  sign = 1;
3456
0
  if(*p=='-')
3457
0
  {
3458
0
    sign = -1;
3459
0
    p++;
3460
0
  }
3461
0
  sp->pvp.pvi.u.ival = 0;
3462
0
  while(p<in->s+in->len && *p>='0' && *p<='9')
3463
0
  {
3464
0
    sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0';
3465
0
    p++;
3466
0
  }
3467
0
  if(p!=in->s+in->len)
3468
0
  {
3469
0
    LM_ERR("invalid index [%.*s]\n", in->len, in->s);
3470
0
    return -1;
3471
0
  }
3472
0
  sp->pvp.pvi.u.ival *= sign;
3473
0
  sp->pvp.pvi.type = PV_IDX_INT;
3474
3475
0
  return 0;
3476
0
}
3477
3478
int pv_init_iname(pv_spec_p sp, int param)
3479
108
{
3480
108
  if(sp==NULL)
3481
0
    return -1;
3482
108
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3483
108
  sp->pvp.pvn.u.isname.name.n = param;
3484
108
  return 0;
3485
108
}
3486
3487
10.7k
static int pv_get_line_number(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res){
3488
10.7k
  int l;
3489
10.7k
  char *ch;
3490
3491
10.7k
  if (param==NULL) {
3492
0
    LM_CRIT("BUG - bad parameters\n");
3493
0
    return -1;
3494
0
  }
3495
3496
10.7k
  if(res == NULL) {
3497
0
    return -1;
3498
0
  }
3499
3500
10.7k
  res->ri = curr_action_line;
3501
10.7k
  ch = int2str( (unsigned long)res->ri, &l);
3502
3503
10.7k
  res->rs.s = ch;
3504
10.7k
  res->rs.len = l;
3505
3506
10.7k
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
3507
3508
10.7k
  return 0;
3509
10.7k
}
3510
3511
10.7k
static int pv_get_cfg_file_name(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res){
3512
3513
10.7k
  if (param==NULL) {
3514
0
    LM_CRIT("BUG - bad parameters\n");
3515
0
    return -1;
3516
0
  }
3517
3518
10.7k
  if(res == NULL) {
3519
0
    return -1;
3520
0
  }
3521
3522
10.7k
  res->rs.s = curr_action_file;
3523
10.7k
  res->rs.len = (res->rs.s)?(strlen(res->rs.s)):(0);
3524
3525
10.7k
  res->flags = PV_VAL_STR;
3526
3527
10.7k
  return 0;
3528
10.7k
}
3529
3530
3531
static int pv_set_log_level(struct sip_msg* msg, pv_param_t *param, int op,
3532
                              pv_value_t *val)
3533
0
{
3534
0
  if(param==NULL)
3535
0
  {
3536
0
    LM_ERR("bad parameters\n");
3537
0
    return -1;
3538
0
  }
3539
3540
0
  if(val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0) {
3541
    /* reset the value to default */
3542
0
    reset_proc_log_level();
3543
0
  } else {
3544
0
    if ((val->flags&PV_TYPE_INT)==0) {
3545
0
      LM_ERR("input for $log_level found not to be an integer\n");
3546
0
      return -1;
3547
0
    }
3548
0
    set_proc_log_level(val->ri);
3549
0
  }
3550
3551
0
  return 0;
3552
0
}
3553
3554
static int pv_get_log_level(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
3555
10.7k
{
3556
10.7k
  int l;
3557
3558
10.7k
  if (param==NULL) {
3559
0
    LM_CRIT("BUG - bad parameters\n");
3560
0
    return -1;
3561
0
  }
3562
3563
10.7k
  if(res == NULL) {
3564
0
    return -1;
3565
0
  }
3566
3567
10.7k
  res->ri = *log_level;
3568
10.7k
  res->rs.s = sint2str( (long)res->ri, &l);
3569
10.7k
  res->rs.len = l;
3570
3571
10.7k
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
3572
3573
10.7k
  return 0;
3574
10.7k
}
3575
3576
static int pv_set_xlog_level(struct sip_msg* msg, pv_param_t *param, int op,
3577
                              pv_value_t *val)
3578
0
{
3579
0
  if(param==NULL)
3580
0
  {
3581
0
    LM_ERR("bad parameters\n");
3582
0
    return -1;
3583
0
  }
3584
3585
0
  if(val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0) {
3586
    /* reset the value to default */
3587
0
    reset_xlog_level();
3588
0
  } else {
3589
0
    if ((val->flags&PV_TYPE_INT)==0) {
3590
0
      LM_ERR("input for $xlog_level found not to be an integer\n");
3591
0
      return -1;
3592
0
    }
3593
0
    set_local_xlog_level( val->ri );
3594
0
  }
3595
3596
0
  return 0;
3597
0
}
3598
3599
static int pv_get_xlog_level(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
3600
10.7k
{
3601
10.7k
  int l;
3602
3603
10.7k
  if (param==NULL) {
3604
0
    LM_CRIT("BUG - bad parameters\n");
3605
0
    return -1;
3606
0
  }
3607
3608
10.7k
  if(res == NULL) {
3609
0
    return -1;
3610
0
  }
3611
3612
10.7k
  res->ri = *xlog_level;
3613
10.7k
  res->rs.s = sint2str( (long)res->ri, &l);
3614
10.7k
  res->rs.len = l;
3615
3616
10.7k
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
3617
3618
10.7k
  return 0;
3619
10.7k
}
3620
3621
/************** Boolean consts *****************/
3622
3623
static const pv_value_t pv_true = {
3624
  .ri = 1,
3625
  .rs = str_init("true"),
3626
  .flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT,
3627
};
3628
3629
3630
static const pv_value_t pv_false = {
3631
  .ri = 0,
3632
  .rs = str_init("false"),
3633
  .flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT,
3634
};
3635
3636
3637
/************** MSG FLAGS function *****************/
3638
3639
static int msg_flag_parse_name(pv_spec_p sp, const str *in)
3640
0
{
3641
0
  unsigned int idx;
3642
0
  if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
3643
0
    return -1;
3644
3645
0
  if ( (idx=fixup_flag(FLAG_TYPE_MSG, in))==NAMED_FLAG_ERROR) {
3646
0
    LM_ERR("failed to fix the flag <%.*s>\n",in->len,in->s);
3647
0
    return -1;
3648
0
  }
3649
3650
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3651
0
  sp->pvp.pvn.u.isname.type = 0;
3652
3653
0
  sp->pvp.pvn.u.isname.name.n = idx;
3654
3655
0
  return 0;
3656
0
}
3657
3658
3659
static int msg_flag_set(struct sip_msg* msg, pv_param_t *param, int op,
3660
                              pv_value_t *val)
3661
0
{
3662
0
  if(param==NULL) {
3663
0
    LM_ERR("bad parameters\n");
3664
0
    return -1;
3665
0
  }
3666
3667
0
  if (val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0 ||
3668
0
  (val->flags&PV_TYPE_INT)==0 ) {
3669
0
    LM_ERR("input for $msg.flag() found not to be an integer\n");
3670
0
    return -1;
3671
0
  }
3672
3673
0
  if (val->ri==0)
3674
0
    resetflag (msg, (unsigned int)param->pvn.u.isname.name.n);
3675
0
  else
3676
0
    setflag( msg, (unsigned int)param->pvn.u.isname.name.n);
3677
3678
0
  return 0;
3679
0
}
3680
3681
3682
static int msg_flag_get(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
3683
0
{
3684
0
  if (param==NULL||res==NULL) {
3685
0
    LM_CRIT("BUG - bad parameters\n");
3686
0
    return -1;
3687
0
  }
3688
3689
0
  if ( isflagset( msg, (unsigned int)param->pvn.u.isname.name.n)==1 ) {
3690
0
    *res = pv_true;
3691
0
  } else {
3692
0
    *res = pv_false;
3693
0
  }
3694
0
  return 0;
3695
0
}
3696
3697
3698
/************** MSG TYPE function *****************/
3699
3700
static int msg_is_request_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
3701
10.7k
{
3702
10.7k
  if (param==NULL||res==NULL) {
3703
0
    LM_CRIT("BUG - bad parameters\n");
3704
0
    return -1;
3705
0
  }
3706
3707
10.7k
  if ( msg->first_line.type==SIP_REQUEST ) {
3708
10.7k
    *res = pv_true;
3709
10.7k
  } else {
3710
4
    *res = pv_false;
3711
4
  }
3712
10.7k
  return 0;
3713
10.7k
}
3714
3715
3716
static int msg_type_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
3717
10.7k
{
3718
10.7k
  if (param==NULL||res==NULL) {
3719
0
    LM_CRIT("BUG - bad parameters\n");
3720
0
    return -1;
3721
0
  }
3722
3723
10.7k
  if ( msg->first_line.type==SIP_REQUEST ) {
3724
10.7k
    res->rs.s = "request";
3725
10.7k
    res->rs.len = 7;
3726
10.7k
  } else {
3727
4
    res->rs.s = "reply";
3728
4
    res->rs.len = 5;
3729
4
  }
3730
3731
10.7k
  res->flags = PV_VAL_STR;
3732
3733
10.7k
  return 0;
3734
10.7k
}
3735
3736
3737
3738
/************** BRANCH FLAGS function *****************/
3739
3740
static int branch_flag_parse_name(pv_spec_p sp, const str *in)
3741
0
{
3742
0
  unsigned int idx;
3743
0
  if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
3744
0
    return -1;
3745
3746
0
  if ( (idx=fixup_flag(FLAG_TYPE_BRANCH, in))==NAMED_FLAG_ERROR) {
3747
0
    LM_ERR("failed to fix the flag <%.*s>\n",in->len,in->s);
3748
0
    return -1;
3749
0
  }
3750
3751
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3752
0
  sp->pvp.pvn.u.isname.type = 0;
3753
3754
0
  sp->pvp.pvn.u.isname.name.n = idx;
3755
3756
0
  return 0;
3757
0
}
3758
3759
3760
static int branch_flag_set(struct sip_msg* msg, pv_param_t *param, int op,
3761
                              pv_value_t *val)
3762
0
{
3763
0
  int idx;
3764
0
  int idxf;
3765
3766
0
  if(param==NULL) {
3767
0
    LM_ERR("bad parameters\n");
3768
0
    return -1;
3769
0
  }
3770
3771
0
  if (val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0 ||
3772
0
  (val->flags&PV_TYPE_INT)==0 ) {
3773
0
    LM_ERR("input for $branch.flag() found not to be an integer\n");
3774
0
    return -1;
3775
0
  }
3776
3777
  /* get the index */
3778
0
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
3779
0
    LM_ERR("invalid index\n");
3780
0
    return -1;
3781
0
  }
3782
3783
0
  if(idxf==PV_IDX_ALL) {
3784
0
    LM_ERR("SCRIPT BUG - * not allowed in branch flag assignment\n");
3785
0
    return -1;
3786
0
  }
3787
3788
0
  if (idx<0) {
3789
0
    idx = get_nr_branches() + idx;
3790
0
  }
3791
3792
0
  if (idx<0 || idx>=get_nr_branches()) {
3793
0
    LM_DBG("inexisting branch flag assignment [%d/%d]\n",
3794
0
      get_nr_branches(), idx);
3795
0
    return -1;
3796
0
  }
3797
3798
0
  if (val->ri==0)
3799
0
    resetbflag (msg, idx, param->pvn.u.isname.name.n);
3800
0
  else
3801
0
    setbflag( msg, idx, param->pvn.u.isname.name.n);
3802
3803
0
  return 0;
3804
0
}
3805
3806
3807
static int branch_flag_get(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
3808
0
{
3809
0
  int idx;
3810
0
  int idxf;
3811
3812
0
  if (param==NULL||res==NULL) {
3813
0
    LM_CRIT("BUG - bad parameters\n");
3814
0
    return -1;
3815
0
  }
3816
3817
  /* get the index */
3818
0
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
3819
0
    LM_ERR("invalid index\n");
3820
0
    return -1;
3821
0
  }
3822
3823
0
  if(idxf==PV_IDX_ALL) {
3824
0
    LM_ERR("SCRIPT BUG - * not allowed in branch flag reading\n");
3825
0
    return -1;
3826
0
  }
3827
3828
0
  if (idx<0) {
3829
0
    idx = get_nr_branches() + idx;
3830
0
  }
3831
3832
0
  if (idx<0 || idx>=get_nr_branches()) {
3833
0
    LM_DBG("inexisting branch flag reading [%d/%d]\n",
3834
0
      get_nr_branches(), idx);
3835
0
    return -1;
3836
0
  }
3837
3838
0
  if ( isbflagset( msg, idx, param->pvn.u.isname.name.n)==1 ) {
3839
0
    *res = pv_true;
3840
0
  } else {
3841
0
    *res = pv_false;
3842
0
  }
3843
0
  return 0;
3844
0
}
3845
3846
3847
/********** generic helper functions ***************/
3848
3849
/**
3850
 * the table with core pseudo-variables
3851
 */
3852
#ifndef FUZZ_BUILD
3853
static
3854
#endif
3855
const pv_export_t _pv_names_table[] = {
3856
  {str_const_init("avp"), PVT_AVP, pv_get_avp, pv_set_avp,
3857
    pv_parse_avp_name, pv_parse_avp_index, 0, 0},
3858
  {str_const_init("hdr"), PVT_HDR, pv_get_hdr, 0, pv_parse_hdr_name,
3859
    pv_parse_index, 0, 0},
3860
  {str_const_init("hdr_name"), PVT_HDR_NAME, pv_get_hdr_name, 0, 0,
3861
    pv_parse_index, 0, 0},
3862
  {str_const_init("hdrcnt"), PVT_HDRCNT, pv_get_hdrcnt, 0, pv_parse_hdr_name, 0, 0, 0},
3863
  {str_const_init("var"), PVT_SCRIPTVAR, pv_get_scriptvar,
3864
    pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0},
3865
  {str_const_init("ai"), /* */
3866
    PVT_PAI_URI, pv_get_pai, 0,
3867
    0, 0, 0, 0},
3868
  {str_const_init("au"), /* */
3869
    PVT_AUTH_USERNAME, pv_get_authattr, 0,
3870
    0, 0, pv_init_iname, 1},
3871
  {str_const_init("ar"), /* auth realm */
3872
    PVT_AUTH_REALM, pv_get_authattr, 0,
3873
    0, 0, pv_init_iname, 2},
3874
  {str_const_init("adu"), /* auth digest uri */
3875
    PVT_AUTH_DURI, pv_get_authattr, 0,
3876
    0, 0, pv_init_iname, 3},
3877
  {str_const_init("ad"), /* */
3878
    PVT_AUTH_DOMAIN, pv_get_authattr, 0,
3879
    0, 0, pv_init_iname, 4},
3880
  {str_const_init("an"), /* */
3881
    PVT_AUTH_NONCE, pv_get_authattr, 0,
3882
    0, 0, pv_init_iname, 5},
3883
  {str_const_init("auth.nonce"), /* */
3884
    PVT_AUTH_NONCE, pv_get_authattr, 0,
3885
    0, 0, pv_init_iname, 5},
3886
  {str_const_init("auth.resp"), /* */
3887
    PVT_AUTH_RESPONSE, pv_get_authattr, 0,
3888
    0, 0, pv_init_iname, 6},
3889
  {str_const_init("auth.cnonce"), /* */
3890
    PVT_AUTH_CNONCE, pv_get_authattr, 0,
3891
    0, 0, pv_init_iname, 7},
3892
  {str_const_init("auth.opaque"), /* */
3893
    PVT_AUTH_OPAQUE, pv_get_authattr, 0,
3894
    0, 0, pv_init_iname, 8},
3895
  {str_const_init("auth.alg"), /* */
3896
    PVT_AUTH_ALGORITHM, pv_get_authattr, 0,
3897
    0, 0, pv_init_iname, 9},
3898
  {str_const_init("auth.qop"), /* */
3899
    PVT_AUTH_QOP, pv_get_authattr, 0,
3900
    0, 0, pv_init_iname, 10},
3901
  {str_const_init("auth.nc"), /* */
3902
    PVT_AUTH_NONCE_COUNT, pv_get_authattr, 0,
3903
    0, 0, pv_init_iname, 11},
3904
  {str_const_init("aU"), /* */
3905
    PVT_AUTH_USERNAME_WHOLE, pv_get_authattr, 0,
3906
    0, 0, pv_init_iname, 99},
3907
  {str_const_init("Au"), /* */
3908
    PVT_ACC_USERNAME, pv_get_acc_username, 0,
3909
    0, 0, pv_init_iname, 1},
3910
  {str_const_init("bf"), /* */
3911
    PVT_BFLAGS, pv_get_bflags, 0,
3912
    0, 0, 0, 0},
3913
  {str_const_init("branch"), /* */
3914
    PVT_BRANCH, pv_get_branch_fields, pv_set_branch,
3915
    0, 0, 0, 0},
3916
  {str_const_init("branch"), /* */
3917
    PVT_BRANCH, pv_get_branch_fields, pv_set_branch_fields,
3918
    pv_parse_branch_name, pv_parse_index, 0, 0},
3919
  {str_const_init("branch.flag"), /* */
3920
    PVT_BRANCH_FLAG, branch_flag_get, branch_flag_set,
3921
    branch_flag_parse_name, pv_parse_index, 0, 0},
3922
  {str_const_init("ci"), /* */
3923
    PVT_CALLID, pv_get_callid, 0,
3924
    0, 0, 0, 0},
3925
  {str_const_init("cl"), /* */
3926
    PVT_CONTENT_LENGTH, pv_get_content_length, 0,
3927
    0, 0, 0, 0},
3928
  {str_const_init("cs"), /* */
3929
    PVT_CSEQ, pv_get_cseq, 0,
3930
    0, 0, 0, 0},
3931
  {str_const_init("ct"), /* */
3932
    PVT_CONTACT, pv_get_contact_body, 0,
3933
    0, pv_parse_index, 0, 0},
3934
  {str_const_init("ct.fields"), /* */
3935
    PVT_CONTACT, pv_get_contact_body, 0,
3936
    pv_parse_ct_name, pv_parse_index, 0, 0},
3937
  {str_const_init("cT"), /* */
3938
    PVT_CONTENT_TYPE, pv_get_content_type, 0,
3939
    0, pv_parse_index, 0, 0},
3940
  {str_const_init("dd"), /* */
3941
    PVT_DSTURI_DOMAIN, pv_get_dsturi_attr, pv_set_dsturi_host,
3942
    0, 0, pv_init_iname, 1},
3943
  {str_const_init("di"), /* */
3944
    PVT_DIVERSION_URI, pv_get_diversion, 0,
3945
    0, 0, pv_init_iname, 1},
3946
  {str_const_init("dir"), /* */
3947
    PVT_DIV_REASON, pv_get_diversion, 0,
3948
    0, 0, pv_init_iname, 2},
3949
  {str_const_init("dip"), /* */
3950
    PVT_DIV_PRIVACY, pv_get_diversion, 0,
3951
    0, 0, pv_init_iname, 3},
3952
  {str_const_init("dp"), /* */
3953
    PVT_DSTURI_PORT, pv_get_dsturi_attr, pv_set_dsturi_port,
3954
    0, 0, pv_init_iname, 2},
3955
  {str_const_init("dP"), /* */
3956
    PVT_DSTURI_PROTOCOL, pv_get_dsturi_attr, 0,
3957
    0, 0, pv_init_iname, 3},
3958
  {str_const_init("ds"), /* */
3959
    PVT_DSET, pv_get_dset, 0,
3960
    0, 0, 0, 0},
3961
  {str_const_init("du"), /* */
3962
    PVT_DSTURI, pv_get_dsturi, pv_set_dsturi,
3963
    0, 0, 0, 0},
3964
  {str_const_init("duri"), /* */
3965
    PVT_DSTURI, pv_get_dsturi, pv_set_dsturi,
3966
    0, 0, 0, 0},
3967
  {str_const_init("err.class"), /* */
3968
    PVT_ERR_CLASS, pv_get_errinfo_attr, 0,
3969
    0, 0, 0, 0},
3970
  {str_const_init("err.level"), /* */
3971
    PVT_ERR_LEVEL, pv_get_errinfo_attr, 0,
3972
    0, 0, pv_init_iname, 1},
3973
  {str_const_init("err.info"), /* */
3974
    PVT_ERR_INFO, pv_get_errinfo_attr, 0,
3975
    0, 0, pv_init_iname, 2},
3976
  {str_const_init("err.rcode"), /* */
3977
    PVT_ERR_RCODE, pv_get_errinfo_attr, 0,
3978
    0, 0, pv_init_iname, 3},
3979
  {str_const_init("err.rreason"), /* */
3980
    PVT_ERR_RREASON, pv_get_errinfo_attr, 0,
3981
    0, 0, pv_init_iname, 4},
3982
  {str_const_init("fd"), /* */
3983
    PVT_FROM_DOMAIN, pv_get_from_attr, 0,
3984
    0, 0, pv_init_iname, 3},
3985
  {str_const_init("from.domain"), /* */
3986
    PVT_FROM_DOMAIN, pv_get_from_attr, 0,
3987
    0, 0, pv_init_iname, 3},
3988
  {str_const_init("fn"), /* */
3989
    PVT_FROM_DISPLAYNAME, pv_get_from_attr, 0,
3990
    0, 0, pv_init_iname, 5},
3991
  {str_const_init("ft"), /* */
3992
    PVT_FROM_TAG, pv_get_from_attr, 0,
3993
    0, 0, pv_init_iname, 4},
3994
  {str_const_init("fu"), /* */
3995
    PVT_FROM, pv_get_from_attr, 0,
3996
    0, 0, pv_init_iname, 1},
3997
  {str_const_init("from"), /* */
3998
    PVT_FROM, pv_get_from_attr, 0,
3999
    0, 0, pv_init_iname, 1},
4000
  {str_const_init("fU"), /* */
4001
    PVT_FROM_USERNAME, pv_get_from_attr, 0,
4002
    0, 0, pv_init_iname, 2},
4003
  {str_const_init("from.user"), /* */
4004
    PVT_FROM_USERNAME, pv_get_from_attr, 0,
4005
    0, 0, pv_init_iname, 2},
4006
  {str_const_init("log_level"), /* per process log level*/
4007
    PVT_LOG_LEVEL, pv_get_log_level, pv_set_log_level,
4008
    0, 0, 0, 0},
4009
  {str_const_init("mb"), /* */
4010
    PVT_MSG_BUF, pv_get_msg_buf, 0,
4011
    0, 0, 0, 0},
4012
  {str_const_init("mf"), /* */
4013
    PVT_FLAGS, pv_get_flags, 0,
4014
    0, 0, 0, 0},
4015
  {str_const_init("msg.flag"), /* */
4016
    PVT_MSG_FLAG, msg_flag_get, msg_flag_set,
4017
    msg_flag_parse_name, 0, 0, 0},
4018
  {str_const_init("msg.is_request"), /* */
4019
    PVT_MSG_FLAG, msg_is_request_get, 0,
4020
    0, 0, 0, 0},
4021
  {str_const_init("msg.type"), /* */
4022
    PVT_MSG_FLAG, msg_type_get, 0,
4023
    0, 0, 0, 0},
4024
  {str_const_init("mi"), /* */
4025
    PVT_MSGID, pv_get_msgid, 0,
4026
    0, 0, 0, 0},
4027
  {str_const_init("ml"), /* */
4028
    PVT_MSG_LEN, pv_get_msg_len, 0,
4029
    0, 0, 0, 0},
4030
  {str_const_init("od"), /* */
4031
    PVT_OURI_DOMAIN, pv_get_ouri_attr, 0,
4032
    0, 0, pv_init_iname, 2},
4033
  {str_const_init("op"), /* */
4034
    PVT_OURI_PORT, pv_get_ouri_attr, 0,
4035
    0, 0, pv_init_iname, 3},
4036
  {str_const_init("oP"), /* */
4037
    PVT_OURI_PROTOCOL, pv_get_ouri_attr, 0,
4038
    0, 0, pv_init_iname, 4},
4039
  {str_const_init("ou"), /* */
4040
    PVT_OURI, pv_get_ouri, 0,
4041
    0, 0, 0, 0},
4042
  {str_const_init("ouri"), /* */
4043
    PVT_OURI, pv_get_ouri, 0,
4044
    0, 0, 0, 0},
4045
  {str_const_init("oU"), /* */
4046
    PVT_OURI_USERNAME, pv_get_ouri_attr, 0,
4047
    0, 0, pv_init_iname, 1},
4048
  {str_const_init("path"), /* */
4049
    PVT_PATH, pv_get_path, 0,
4050
    0, 0, 0, 0},
4051
  {str_const_init("pd"), /* */
4052
    PVT_PPI_DOMAIN, pv_get_ppi_attr, 0,
4053
    0, 0, pv_init_iname, 3},
4054
  {str_const_init("pn"), /* */
4055
    PVT_PPI_DISPLAYNAME, pv_get_ppi_attr, 0,
4056
    0, 0, pv_init_iname, 4},
4057
  {str_const_init("pp"), /* */
4058
    PVT_PID, pv_get_pid, 0,
4059
    0, 0, 0, 0},
4060
  {str_const_init("pu"), /* */
4061
    PVT_PPI, pv_get_ppi_attr, 0,
4062
    0, 0, pv_init_iname, 1},
4063
  {str_const_init("pU"), /* */
4064
    PVT_PPI_USERNAME, pv_get_ppi_attr, 0,
4065
    0, 0, pv_init_iname, 2},
4066
  {str_const_init("rb"), /* */
4067
    PVT_MSG_BODY, pv_get_msg_body, 0,
4068
    0, pv_parse_index, 0, 0},
4069
  {str_const_init("rb"), /* */
4070
    PVT_MSG_BODY, pv_get_msg_body, 0,
4071
    pv_parse_rb_name, pv_parse_index, 0, 0},
4072
  {str_const_init("rc"), /* */
4073
    PVT_RETURN_CODE, pv_get_return_code, 0,
4074
    0, 0, 0, 0},
4075
  {str_const_init("retcode"), /* */
4076
    PVT_RETURN_CODE, pv_get_return_code, 0,
4077
    0, 0, 0, 0},
4078
  {str_const_init("rd"), /* */
4079
    PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host,
4080
    0, 0, pv_init_iname, 2},
4081
  {str_const_init("ruri.domain"), /* */
4082
    PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host,
4083
    0, 0, pv_init_iname, 2},
4084
  {str_const_init("re"), /* */
4085
    PVT_RPID_URI, pv_get_rpid, 0,
4086
    0, 0, 0, 0},
4087
  {str_const_init("rm"), /* */
4088
    PVT_METHOD, pv_get_method, 0,
4089
    0, 0, 0, 0},
4090
  {str_const_init("route"), /* */
4091
    PVT_ROUTE, pv_get_route, 0,
4092
    0, pv_parse_index, 0, 0},
4093
  {str_const_init("route.name"), /* */
4094
    PVT_ROUTE_NAME, pv_get_route_name, 0,
4095
    0, pv_parse_index, 0, 0},
4096
  {str_const_init("route.type"), /* */
4097
    PVT_ROUTE_TYPE, pv_get_route_type, 0,
4098
    0, pv_parse_index, 0, 0},
4099
  {str_const_init("rp"), /* */
4100
    PVT_RURI_PORT, pv_get_ruri_attr, pv_set_ruri_port,
4101
    0, 0, pv_init_iname, 3},
4102
  {str_const_init("rP"), /* */
4103
    PVT_RURI_PROTOCOL, pv_get_ruri_attr, 0,
4104
    0, 0, pv_init_iname, 4},
4105
  {str_const_init("rr"), /* */
4106
    PVT_REASON, pv_get_reason, 0,
4107
    0, 0, 0, 0},
4108
  {str_const_init("rs"), /* */
4109
    PVT_STATUS, pv_get_status, 0,
4110
    0, 0, 0, 0},
4111
  {str_const_init("rt"), /* */
4112
    PVT_REFER_TO, pv_get_refer_to, 0,
4113
    0, 0, 0, 0},
4114
  {str_const_init("ru"), /* */
4115
    PVT_RURI, pv_get_ruri, pv_set_ruri,
4116
    0, 0, 0, 0},
4117
  {str_const_init("ruri"), /* */
4118
    PVT_RURI, pv_get_ruri, pv_set_ruri,
4119
    0, 0, 0, 0},
4120
  {str_const_init("ru_q"), /* */
4121
    PVT_RU_Q, pv_get_ru_q, pv_set_ru_q,
4122
    0, 0, 0, 0},
4123
  {str_const_init("rU"), /* */
4124
    PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user,
4125
    0, 0, pv_init_iname, 1},
4126
  {str_const_init("ruri.user"), /* */
4127
    PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user,
4128
    0, 0, pv_init_iname, 1},
4129
  {str_const_init("src_ip"), /* */
4130
    PVT_SRCIP, pv_get_srcip, 0,
4131
    0, 0, 0, 0},
4132
  {str_const_init("socket_in"), /* */
4133
    PVT_SOCKET_IN, pv_get_socket_in_fields, NULL,
4134
    0, 0, 0, 0},
4135
  {str_const_init("socket_in"), /* */
4136
    PVT_SOCKET_IN, pv_get_socket_in_fields, NULL,
4137
    pv_parse_socket_name, 0, 0, 0},
4138
  {str_const_init("socket_out"), /* */
4139
    PVT_SOCKET_OUT, pv_get_socket_out_fields, pv_set_force_sock,
4140
    0, 0, 0, 0},
4141
  {str_const_init("socket_out"), /* */
4142
    PVT_SOCKET_OUT, pv_get_socket_out_fields, NULL,
4143
    pv_parse_socket_name, 0, 0, 0},
4144
  {str_const_init("si"), /* */
4145
    PVT_SRCIP, pv_get_srcip, 0,
4146
    0, 0, 0, 0},
4147
  {str_const_init("sp"), /* */
4148
    PVT_SRCPORT, pv_get_srcport, 0,
4149
    0, 0, 0, 0},
4150
  {str_const_init("td"), /* */
4151
    PVT_TO_DOMAIN, pv_get_to_attr, 0,
4152
    0, 0, pv_init_iname, 3},
4153
  {str_const_init("to.domain"), /* */
4154
    PVT_TO_DOMAIN, pv_get_to_attr, 0,
4155
    0, 0, pv_init_iname, 3},
4156
  {str_const_init("time"), /* */
4157
    PVT_TIME, pv_get_formated_time, 0,
4158
    pv_parse_time_name, 0, 0, 0},
4159
  {str_const_init("tn"), /* */
4160
    PVT_TO_DISPLAYNAME, pv_get_to_attr, 0,
4161
    0, 0, pv_init_iname, 5},
4162
  {str_const_init("tt"), /* */
4163
    PVT_TO_TAG, pv_get_to_attr, 0,
4164
    0, 0, pv_init_iname, 4},
4165
  {str_const_init("tu"), /* */
4166
    PVT_TO, pv_get_to_attr, 0,
4167
    0, 0, pv_init_iname, 1},
4168
  {str_const_init("to"), /* */
4169
    PVT_TO, pv_get_to_attr, 0,
4170
    0, 0, pv_init_iname, 1},
4171
  {str_const_init("tU"), /* */
4172
    PVT_TO_USERNAME, pv_get_to_attr, 0,
4173
    0, 0, pv_init_iname, 2},
4174
  {str_const_init("to.user"), /* */
4175
    PVT_TO_USERNAME, pv_get_to_attr, 0,
4176
    0, 0, pv_init_iname, 2},
4177
  {str_const_init("Tf"), /* */
4178
    PVT_TIMEF, pv_get_timef, 0,
4179
    0, 0, 0, 0},
4180
  {str_const_init("Ts"), /* */
4181
    PVT_TIMES, pv_get_times, 0,
4182
    0, 0, 0, 0},
4183
  {str_const_init("Tsm"), /* */
4184
    PVT_TIMES, pv_get_timem, 0,
4185
    0, 0, 0, 0},
4186
  {str_const_init("TS"), /* */
4187
    PVT_TIMES, pv_get_start_times, 0,
4188
    0, 0, 0, 0},
4189
  {str_const_init("ua"), /* */
4190
    PVT_USERAGENT, pv_get_useragent, 0,
4191
    0, 0, 0, 0},
4192
  {str_const_init("C"), PVT_COLOR, pv_get_color, 0,
4193
    pv_parse_color_name, 0, 0, 0 },
4194
  {str_const_init("argv"), PVT_ARGV, pv_get_argv, 0,
4195
    pv_parse_argv_name, 0, 0, 0 },
4196
  {str_const_init("param"), PVT_ROUTE_PARAM, pv_get_param, 0,
4197
    pv_parse_param_name, 0, 0, 0 },
4198
  {str_const_init("cfg_line"), PVT_LINE_NUMBER, pv_get_line_number, 0,
4199
    0, 0, 0, 0 },
4200
  {str_const_init("cfg_file"), PVT_CFG_FILE_NAME, pv_get_cfg_file_name, 0,
4201
  0, 0, 0, 0 },
4202
  {str_const_init("xlog_level"), PVT_XLOG_LEVEL, pv_get_xlog_level,
4203
    pv_set_xlog_level, 0, 0, 0, 0 },
4204
  {{0,0}, 0, 0, 0, 0, 0, 0, 0}
4205
};
4206
4207
static const pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e, int has_name)
4208
240
{
4209
240
  int i;
4210
240
  pv_extra_p pvi;
4211
240
  int found;
4212
4213
240
  if(pvname==0 || e==0)
4214
0
  {
4215
0
    LM_ERR("bad parameters\n");
4216
0
    return NULL;
4217
0
  }
4218
  /* search in main table */
4219
16.0k
  for(i=0; _pv_names_table[i].name.s!=0; i++)
4220
16.0k
  {
4221
16.0k
    if(_pv_names_table[i].name.len==pvname->len
4222
16.0k
      && !((has_name?1:0) ^ (_pv_names_table[i].parse_name?1:0))
4223
16.0k
      && memcmp(_pv_names_table[i].name.s, pvname->s, pvname->len)==0)
4224
218
    {
4225
      /*LM_DBG("found [%.*s] [%d]\n", pvname->len, pvname->s,
4226
          _pv_names_table[i].type);*/
4227
      /* copy data from table to spec */
4228
218
      e->type = _pv_names_table[i].type;
4229
218
      e->getf = _pv_names_table[i].getf;
4230
218
      e->setf = _pv_names_table[i].setf;
4231
218
      return &_pv_names_table[i];
4232
218
    }
4233
16.0k
  }
4234
  /* search in extra list */
4235
22
  if(_pv_extra_list==0)
4236
22
  {
4237
22
    LM_DBG("extra items list is empty\n");
4238
22
    return NULL;
4239
22
  }
4240
0
  pvi = *_pv_extra_list;
4241
0
  while(pvi)
4242
0
  {
4243
0
    if(pvi->pve.name.len>pvname->len)
4244
0
      break;
4245
0
    if(pvi->pve.name.len==pvname->len)
4246
0
    {
4247
0
      found = strncmp(pvi->pve.name.s, pvname->s, pvname->len);
4248
0
      if(found>0)
4249
0
        break;
4250
0
      if(found==0)
4251
0
      {
4252
0
        LM_DBG("found in extra list [%.*s]\n", pvname->len, pvname->s);
4253
        /* copy data from export to spec */
4254
0
        e->type = pvi->pve.type;
4255
0
        e->getf = pvi->pve.getf;
4256
0
        e->setf = pvi->pve.setf;
4257
0
        return &(pvi->pve);
4258
0
      }
4259
0
    }
4260
0
    pvi = pvi->next;
4261
0
  }
4262
4263
0
  return NULL;
4264
0
}
4265
4266
static int is_pv_valid_char(char c)
4267
1.07k
{
4268
1.07k
  if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')
4269
1.07k
      || (c=='_') || (c=='.'))
4270
1.07k
    return 1;
4271
0
  return 0;
4272
1.07k
}
4273
4274
char* pv_parse_spec(const str *in, const pv_spec_p e)
4275
240
{
4276
240
  char *p;
4277
240
  str s;
4278
240
  str pvname;
4279
240
  str pvcontext;
4280
240
  int pvstate;
4281
240
  int has_inner_name;
4282
240
  trans_t *tr = NULL;
4283
240
  const pv_export_t *pte = NULL;
4284
240
  int n=0;
4285
4286
240
  if(in==NULL || in->s==NULL || e==NULL || *in->s!=PV_MARKER)
4287
0
  {
4288
0
    LM_ERR("bad parameters\n");
4289
0
    return NULL;
4290
0
  }
4291
4292
//  LM_DBG("***** input [%.*s] (%d)\n", in->len, in->s, in->len);
4293
240
  tr = 0;
4294
240
  pvstate = 0;
4295
240
  memset(e, 0, sizeof(pv_spec_t));
4296
240
  p = in->s;
4297
240
  p++;
4298
240
  if(*p==PV_LNBRACKET)
4299
0
  {
4300
0
    p++;
4301
0
    pvstate = 1;
4302
0
  }
4303
240
  pvname.s = p;
4304
240
  if(*p == PV_MARKER) {
4305
0
    p++;
4306
0
    if(pvstate==1)
4307
0
    {
4308
0
      if(*p!=PV_RNBRACKET)
4309
0
        goto error;
4310
0
      p++;
4311
0
    }
4312
0
    e->getf = pv_get_marker;
4313
0
    e->type = PVT_MARKER;
4314
0
    pvname.len = 1;
4315
0
    goto done_all;
4316
0
  }
4317
4318
240
  if (*p==PV_LCBRACKET)
4319
0
  { /* context definition*/
4320
0
    p++;
4321
0
    pvcontext.s = p;
4322
4323
0
    while(is_in_str(p,in) && is_pv_valid_char(*p))
4324
0
      p++;
4325
4326
0
    if(*p != PV_RCBRACKET)
4327
0
    {
4328
0
      LM_ERR("Expected to find the end of the context\n");
4329
0
      return 0;
4330
0
    }
4331
0
    pvcontext.len = p - pvcontext.s;
4332
0
    LM_DBG("Context name is %.*s\n", pvcontext.len, pvcontext.s);
4333
0
    p++;
4334
0
    e->pvc = pv_get_context(&pvcontext);
4335
0
    if(e->pvc == NULL)
4336
0
    {
4337
0
      if(!pvc_before_check)
4338
0
      {
4339
0
        LM_ERR("Requested a non existing pv context\n");
4340
0
        return 0;
4341
0
      }
4342
0
      LM_DBG("No context definition found for [%.*s]\n", pvcontext.len, pvcontext.s);
4343
      /* create a dummy context strcuture to be filled by the register functions */
4344
0
      e->pvc = add_pv_context(&pvcontext, 0);
4345
0
      if(e->pvc == NULL )
4346
0
      {
4347
0
        LM_ERR("Failed to new context\n");
4348
0
        return 0;
4349
0
      }
4350
0
    }
4351
0
  }
4352
4353
240
  pvname.s = p;
4354
1.31k
  while(is_in_str(p,in) && is_pv_valid_char(*p))
4355
1.07k
    p++;
4356
240
  pvname.len = p - pvname.s;
4357
4358
240
  if(pvstate==1)
4359
0
  {
4360
0
    if(*p==PV_RNBRACKET)
4361
0
    { /* full pv name ended here*/
4362
0
      goto done_inm;
4363
0
    } else if(*p==PV_LNBRACKET) {
4364
0
      p++;
4365
0
      pvstate = 2;
4366
0
    } else if(*p==PV_LIBRACKET) {
4367
0
      p++;
4368
0
      pvstate = 3;
4369
0
    } else if(*p==TR_LBRACKET) {
4370
0
      p++;
4371
0
      pvstate = 4;
4372
0
    }
4373
0
    else {
4374
0
      LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
4375
0
          pvstate);
4376
0
      goto error;
4377
0
    }
4378
240
  } else {
4379
240
    if(!is_in_str(p, in)) {
4380
240
      p--;
4381
240
      goto done_inm;
4382
240
    } else if(*p==PV_LNBRACKET) {
4383
0
      p++;
4384
0
      pvstate = 5;
4385
0
    } else {
4386
      /* still in input str, but end of PV */
4387
      /* p is increased at the end, so decrement here */
4388
0
      p--;
4389
0
      goto done_inm;
4390
0
    }
4391
240
  }
4392
4393
240
done_inm:
4394
240
  has_inner_name = (pvstate==2||pvstate==5)?1:0;
4395
240
  if((pte = pv_lookup_spec_name(&pvname, e, has_inner_name))==NULL)
4396
22
  {
4397
22
    LM_ERR("unknown script var $%.*s%s, maybe a 'loadmodule' statement "
4398
22
           "is missing?\n", pvname.len, pvname.s,has_inner_name ? "()":"");
4399
22
    goto error;
4400
22
  }
4401
218
  if(pvstate==2 || pvstate==5)
4402
0
  {
4403
0
    s.s = p;
4404
0
    n = 0;
4405
0
    while(is_in_str(p, in))
4406
0
    {
4407
0
      if(*p==PV_RNBRACKET)
4408
0
      {
4409
0
        if(n==0)
4410
0
          break;
4411
0
        n--;
4412
0
      }
4413
0
      if(*p == PV_LNBRACKET)
4414
0
        n++;
4415
0
      p++;
4416
0
    }
4417
4418
0
    if(!is_in_str(p, in))
4419
0
      goto error;
4420
4421
0
    if(p==s.s)
4422
0
    {
4423
0
      LM_ERR("pvar \"%.*s\" does not get empty name param\n",
4424
0
          pvname.len, pvname.s);
4425
0
      goto error;
4426
0
    }
4427
0
    s.len = p - s.s;
4428
0
    if(pte->parse_name == NULL || pte->parse_name(e, &s)!=0)
4429
0
    {
4430
0
      LM_ERR("pvar \"%.*s\" has an invalid name param [%.*s]\n",
4431
0
          pvname.len, pvname.s, s.len, s.s);
4432
0
      goto error;
4433
0
    }
4434
0
    if(pvstate==2)
4435
0
    {
4436
0
      p++;
4437
0
      if(*p==PV_RNBRACKET)
4438
0
      { /* full pv name ended here*/
4439
0
        goto done_vnm;
4440
0
      } else if(*p==PV_LIBRACKET) {
4441
0
        p++;
4442
0
        pvstate = 3;
4443
0
      } else if(*p==TR_LBRACKET) {
4444
0
        p++;
4445
0
        pvstate = 4;
4446
0
      } else {
4447
0
        LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
4448
0
          pvstate);
4449
0
        goto error;
4450
0
      }
4451
0
    } else {
4452
0
      if(*p==PV_RNBRACKET)
4453
0
      { /* full pv name ended here*/
4454
0
        p++;
4455
0
        goto done_all;
4456
0
      } else {
4457
0
        LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
4458
0
          pvstate);
4459
0
        goto error;
4460
0
      }
4461
0
    }
4462
0
  }
4463
218
done_vnm:
4464
218
  if(pvstate==3)
4465
0
  {
4466
0
    if(pte->parse_index==NULL)
4467
0
    {
4468
0
      LM_ERR("pvar \"%.*s\" does not get index param\n",
4469
0
          pvname.len, pvname.s);
4470
0
      goto error;
4471
0
    }
4472
0
    s.s = p;
4473
0
    n = 0;
4474
0
    while(is_in_str(p, in))
4475
0
    {
4476
0
      if(*p==PV_RIBRACKET)
4477
0
      {
4478
0
        if(n==0)
4479
0
          break;
4480
0
        n--;
4481
0
      }
4482
0
      if(*p == PV_LIBRACKET)
4483
0
        n++;
4484
0
      p++;
4485
0
    }
4486
0
    if(!is_in_str(p, in))
4487
0
      goto error;
4488
4489
0
    if(p==s.s)
4490
0
    {
4491
0
      LM_ERR("pvar \"%.*s\" does not get empty index param\n",
4492
0
          pvname.len, pvname.s);
4493
0
      goto error;
4494
0
    }
4495
0
    s.len = p - s.s;
4496
0
    if(pte->parse_index(e, &s)!=0)
4497
0
    {
4498
0
      LM_ERR("pvar \"%.*s\" has an invalid index param [%.*s]\n",
4499
0
          pvname.len, pvname.s, s.len, s.s);
4500
0
      goto error;
4501
0
    }
4502
0
    p++;
4503
0
    if(*p==PV_RNBRACKET)
4504
0
    { /* full pv name ended here*/
4505
0
      goto done_idx;
4506
0
    } else if(*p==TR_LBRACKET) {
4507
0
      p++;
4508
0
      pvstate = 4;
4509
0
    } else {
4510
0
      LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
4511
0
          pvstate);
4512
0
      goto error;
4513
0
    }
4514
0
  }
4515
218
done_idx:
4516
218
  if(pvstate==4)
4517
0
  {
4518
0
    s.s = p-1;
4519
0
    n = 0;
4520
0
    while(is_in_str(p, in))
4521
0
    {
4522
0
      if(*p==TR_RBRACKET)
4523
0
      {
4524
0
        if(n==0)
4525
0
        {
4526
          /* yet another transformation */
4527
0
          p++;
4528
0
          while(is_in_str(p, in) && (*p==' ' || *p=='\t')) p++;
4529
4530
0
          if(!is_in_str(p, in) || *p != TR_LBRACKET)
4531
0
          {
4532
0
            p--;
4533
0
            break;
4534
0
          }
4535
0
        }
4536
0
        n--;
4537
0
      }
4538
0
      if(*p == TR_LBRACKET)
4539
0
        n++;
4540
0
      p++;
4541
0
    }
4542
0
    if(!is_in_str(p, in))
4543
0
      goto error;
4544
4545
0
    if(p==s.s)
4546
0
    {
4547
0
      LM_ERR("pvar \"%.*s\" does not get empty index param\n",
4548
0
          pvname.len, pvname.s);
4549
0
      goto error;
4550
0
    }
4551
0
    s.len = p - s.s + 1;
4552
4553
0
    p = parse_transformation(&s, &tr);
4554
0
    if(p==NULL)
4555
0
    {
4556
0
      LM_ERR("ERROR:bad tr in pvar name \"%.*s\"\n",
4557
0
          pvname.len, pvname.s);
4558
0
      goto error;
4559
0
    }
4560
0
    if(*p!=PV_RNBRACKET)
4561
0
    {
4562
0
      LM_ERR("bad pvar name \"%.*s\" (%c)!\n", in->len, in->s, *p);
4563
0
      goto error;
4564
0
    }
4565
0
    e->trans = (void*)tr;
4566
0
  }
4567
218
  p++;
4568
4569
218
done_all:
4570
218
  if(pte!=NULL && pte->init_param)
4571
108
    pte->init_param(e, pte->iparam);
4572
218
  return p;
4573
4574
22
error:
4575
22
  if(p!=NULL)
4576
22
    LM_ERR("wrong char [%c/%d] in [%.*s] at [%d (%d)]\n", *p, (int)*p,
4577
22
      in->len, in->s, (int)(p-in->s), pvstate);
4578
0
  else
4579
0
    LM_ERR("invalid parsing in [%.*s] at (%d)\n", in->len, in->s, pvstate);
4580
22
  return NULL;
4581
4582
218
} /* end: pv_parse_spec */
4583
4584
/**
4585
 *
4586
 */
4587
int pv_parse_format(const str *in, pv_elem_p *el)
4588
0
{
4589
0
  char *p, *p0;
4590
  /*int n = 0;*/
4591
0
  pv_elem_p e, e0;
4592
0
  str s;
4593
4594
0
  if(in==NULL || in->s==NULL || el==NULL)
4595
0
    return -1;
4596
4597
  /*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
4598
4599
0
  if(in->len == 0)
4600
0
  {
4601
0
    *el = pkg_malloc(sizeof(pv_elem_t));
4602
0
    if(*el == NULL) {
4603
0
      LM_ERR("not enough pkg memory for PV element (1)\n");
4604
0
      goto error;
4605
0
    }
4606
0
    memset(*el, 0, sizeof(pv_elem_t));
4607
0
    (*el)->text = *in;
4608
0
    return 0;
4609
0
  }
4610
4611
0
  p = in->s;
4612
0
  *el = NULL;
4613
0
  e = e0 = NULL;
4614
4615
0
  while(is_in_str(p,in))
4616
0
  {
4617
0
    e0 = e;
4618
0
    e = pkg_malloc(sizeof(pv_elem_t));
4619
0
    if(!e) {
4620
0
      LM_ERR("not enough pkg memory for PV element (2)\n");
4621
0
      goto error;
4622
0
    }
4623
0
    memset(e, 0, sizeof(pv_elem_t));
4624
    /*n++;*/
4625
0
    if(*el == NULL)
4626
0
      *el = e;
4627
0
    if(e0)
4628
0
      e0->next = e;
4629
4630
0
    e->text.s = p;
4631
0
    while(is_in_str(p,in) && *p!=PV_MARKER)
4632
0
      p++;
4633
0
    e->text.len = p - e->text.s;
4634
4635
0
    if(!is_in_str(p,in))
4636
0
      break;
4637
0
    s.s = p;
4638
0
    s.len = in->s+in->len-p;
4639
0
    p0 = pv_parse_spec(&s, &e->spec);
4640
4641
0
    if(p0==NULL) {
4642
0
      LM_ERR("parsing PV spec failed\n");
4643
0
      goto error;
4644
0
    }
4645
0
    if(!is_in_str(p0,in))
4646
0
      break;
4647
0
    p = p0;
4648
0
  }
4649
  /*LM_DBG("format parsed OK: [%d] items\n", n);*/
4650
4651
0
  if(*el == NULL)
4652
0
    return -1;
4653
4654
0
  return 0;
4655
4656
0
error:
4657
0
  pv_elem_free_all(*el);
4658
0
  *el = NULL;
4659
0
  return -1;
4660
0
}
4661
4662
int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name)
4663
0
{
4664
0
  if(msg==NULL || ip==NULL || name==NULL)
4665
0
    return -1;
4666
0
  memset(name, 0, sizeof(pv_value_t));
4667
4668
0
  if(ip->pvn.type==PV_NAME_INTSTR)
4669
0
  {
4670
0
    if(ip->pvn.u.isname.type&AVP_NAME_STR)
4671
0
    {
4672
0
      name->rs = ip->pvn.u.isname.name.s;
4673
0
      name->flags = PV_VAL_STR;
4674
0
    } else {
4675
0
      name->ri = ip->pvn.u.isname.name.n;
4676
0
      name->flags = PV_VAL_INT|PV_TYPE_INT;
4677
0
    }
4678
0
    return 0;
4679
0
  }
4680
  /* pvar */
4681
0
  if(pv_get_spec_value(msg, (const pv_spec_p)(ip->pvn.u.dname), name)!=0)
4682
0
  {
4683
0
    LM_ERR("cannot get name value\n");
4684
0
    return -1;
4685
0
  }
4686
0
  if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY)
4687
0
  {
4688
0
    LM_ERR("null or empty name\n");
4689
0
    return -1;
4690
0
  }
4691
0
  return 0;
4692
0
}
4693
4694
int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int *avp_name,
4695
    unsigned short *name_type)
4696
0
{
4697
0
  pv_value_t tv;
4698
0
  if(ip==NULL || avp_name==NULL || name_type==NULL)
4699
0
    return -1;
4700
0
  *avp_name = 0;
4701
0
  *name_type = 0;
4702
4703
0
  if(ip->pvn.type==PV_NAME_INTSTR)
4704
0
  {
4705
0
    *name_type = ip->pvn.u.isname.type;
4706
0
    *avp_name = ip->pvn.u.isname.name.n;
4707
0
    *name_type &= AVP_SCRIPT_MASK;
4708
0
    return 0;
4709
0
  }
4710
  /* pvar */
4711
0
  if(pv_get_spec_value(msg, (const pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
4712
0
  {
4713
0
    LM_ERR("cannot get avp value\n");
4714
0
    return -1;
4715
0
  }
4716
0
  if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
4717
0
  {
4718
0
    LM_ERR("null or empty name\n");
4719
0
    return -1;
4720
0
  }
4721
4722
0
  if(!(tv.flags&PV_VAL_STR))
4723
0
    tv.rs.s = int2str(tv.ri, &tv.rs.len);
4724
4725
  /* search the name here */
4726
0
  *avp_name = get_avp_id(&tv.rs);
4727
0
  if (*avp_name == 0) {
4728
0
    LM_ERR("cannot find avp %.*s\n", tv.rs.len, tv.rs.s);
4729
0
    return -1;
4730
0
  }
4731
0
  return 0;
4732
0
}
4733
4734
4735
int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
4736
75.9k
{
4737
75.9k
  pv_value_t tv;
4738
75.9k
  if(ip==NULL || idx==NULL || flags==NULL)
4739
0
    return -1;
4740
4741
75.9k
  *idx = 0;
4742
75.9k
  *flags = ip->pvi.type;
4743
4744
75.9k
  if(ip->pvi.type == 0)
4745
75.9k
    return 0;
4746
4747
0
  if(ip->pvi.type == PV_IDX_ALL || ip->pvi.type == PV_IDX_APPEND) {
4748
0
    return 0;
4749
0
  }
4750
4751
0
  if(ip->pvi.type == PV_IDX_INT)
4752
0
  {
4753
0
    *idx = ip->pvi.u.ival;
4754
0
    return 0;
4755
0
  }
4756
4757
  /* pvar */
4758
0
  if(pv_get_spec_value(msg, (const pv_spec_p)ip->pvi.u.dval, &tv)!=0)
4759
0
  {
4760
0
    LM_ERR("cannot get index value\n");
4761
0
    return -1;
4762
0
  }
4763
0
  if(!(tv.flags & PV_VAL_INT))
4764
0
  {
4765
0
    LM_ERR("invalid index value\n");
4766
0
    return -1;
4767
0
  }
4768
0
  *idx = tv.ri;
4769
0
  return 0;
4770
0
}
4771
4772
/* function to set pv value */
4773
int pv_set_value(struct sip_msg* msg, pv_spec_p sp,
4774
    int op, pv_value_t *value)
4775
0
{
4776
0
  struct sip_msg* pv_msg;
4777
4778
0
  if(msg==NULL || sp==NULL || sp->setf==NULL || sp->type==PVT_NONE)
4779
0
  {
4780
0
    LM_ERR("bad parameters\n");
4781
0
    return -1;
4782
0
  }
4783
4784
0
  if(sp->pvc && sp->pvc->contextf)
4785
0
  {
4786
0
    pv_msg = sp->pvc->contextf(msg);
4787
0
    if(pv_msg == NULL || pv_msg==FAKED_REPLY)
4788
0
    {
4789
0
      LM_DBG("Invalid %p pv context message\n",pv_msg);
4790
0
      return -1;
4791
0
    }
4792
0
  }
4793
0
  else
4794
0
    pv_msg = msg;
4795
4796
0
  return (*sp->setf)(pv_msg, &(sp->pvp), op, value);
4797
0
}
4798
4799
int pv_get_spec_value(struct sip_msg* msg, const pv_spec_p sp, pv_value_t *value)
4800
0
{
4801
0
  struct sip_msg* pv_msg;
4802
4803
0
  if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
4804
0
      || sp->type==PVT_NONE)
4805
0
  {
4806
0
    LM_ERR("bad parameters\n");
4807
0
    return -1;
4808
0
  }
4809
4810
0
  memset(value, 0, sizeof(pv_value_t));
4811
4812
0
  if(sp->pvc && sp->pvc->contextf)
4813
0
  {
4814
0
    LM_DBG("Found context function %p\n", sp->pvc->contextf);
4815
0
    pv_msg = sp->pvc->contextf(msg);
4816
0
    if(pv_msg == NULL || pv_msg==FAKED_REPLY)
4817
0
    {
4818
0
      LM_DBG("Invalid %p pv context message\n",pv_msg);
4819
0
      return pv_get_null( NULL, NULL, value);
4820
0
    }
4821
0
  } else {
4822
0
    pv_msg = msg;
4823
0
  }
4824
0
  if((*sp->getf)(pv_msg, &(sp->pvp), value)!=0)
4825
0
    return pv_get_null( NULL, NULL, value);
4826
0
  if(sp->trans)
4827
0
    if (run_transformations(pv_msg, (trans_t*)sp->trans, value)!=0)
4828
0
      return pv_get_null( NULL, NULL, value);
4829
0
  return 0;
4830
0
}
4831
4832
int pv_print_spec(struct sip_msg* msg, const pv_spec_p sp, char *buf, int *len)
4833
0
{
4834
0
  pv_value_t tok;
4835
0
  if(msg==NULL || sp==NULL || buf==NULL || len==NULL)
4836
0
    return -1;
4837
4838
0
  if(*len <= 0)
4839
0
    return -1;
4840
4841
0
  memset(&tok, 0, sizeof(pv_value_t));
4842
4843
  /* put the value of the specifier */
4844
0
  if(pv_get_spec_value(msg, sp, &tok)==0)
4845
0
  {
4846
0
    if(tok.flags&PV_VAL_NULL)
4847
0
      tok.rs = str_null;
4848
0
    if(tok.rs.len < *len)
4849
0
      memcpy(buf, tok.rs.s, tok.rs.len);
4850
0
    else
4851
0
      goto overflow;
4852
0
  }
4853
4854
0
  *len = tok.rs.len;
4855
0
  buf[tok.rs.len] = '\0';
4856
0
  return 0;
4857
4858
0
overflow:
4859
0
  LM_ERR("buffer overflow -- increase the buffer size...\n");
4860
0
  return -1;
4861
0
}
4862
4863
4864
int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
4865
0
{
4866
0
  int n;
4867
0
  pv_value_t tok;
4868
0
  str print;
4869
0
  pv_elem_p it;
4870
0
  char *cur;
4871
4872
0
  if(msg==NULL || list==NULL || buf==NULL || len==NULL)
4873
0
    return -1;
4874
4875
0
  if(*len <= 0)
4876
0
    return -1;
4877
4878
0
  *buf = '\0';
4879
0
  cur = buf;
4880
4881
0
  n = 0;
4882
0
  for (it=list; it; it=it->next)
4883
0
  {
4884
    /* put the text */
4885
0
    if(it->text.s && it->text.len>0)
4886
0
    {
4887
0
      if(n+it->text.len < *len)
4888
0
      {
4889
0
        memcpy(cur, it->text.s, it->text.len);
4890
0
        n += it->text.len;
4891
0
        cur += it->text.len;
4892
0
      } else {
4893
0
        LM_ERR("no more space for text [%d][%d]\n", n, it->text.len);
4894
0
        goto overflow;
4895
0
      }
4896
0
    }
4897
    /* put the value of the specifier */
4898
0
    if(it->spec.type!=PVT_NONE
4899
0
        && pv_get_spec_value(msg, &(it->spec), &tok)==0)
4900
0
    {
4901
0
      print = pv_value_print(&tok);
4902
0
      if (n + print.len >= *len) {
4903
0
        LM_ERR("no more space for spec value [%d][%d]\n",
4904
0
               n, print.len);
4905
0
        goto overflow;
4906
0
      }
4907
4908
0
      memcpy(cur, print.s, print.len);
4909
0
      n += print.len;
4910
0
      cur += print.len;
4911
0
    }
4912
0
  }
4913
4914
0
  goto done;
4915
4916
0
overflow:
4917
0
  if (is_pv_print_buf(buf))
4918
0
    LM_ERR("buffer too small -- increase 'pv_print_buf_size' from [%d]\n",
4919
0
        *len);
4920
0
  else
4921
0
    LM_ERR("buffer too small -- increase the buffer size "
4922
0
        "from [%d]...\n", *len);
4923
0
  return -1;
4924
4925
0
done:
4926
#ifdef EXTRA_DEBUG
4927
  LM_DBG("final buffer length %d\n", n);
4928
#endif
4929
0
  *cur = '\0';
4930
0
  *len = n;
4931
0
  return 0;
4932
0
}
4933
4934
4935
4936
pvname_list_t* parse_pvname_list(str *in, unsigned int type)
4937
0
{
4938
0
  pvname_list_t* head = NULL;
4939
0
  pvname_list_t* al = NULL;
4940
0
  pvname_list_t* last = NULL;
4941
0
  char *p;
4942
0
  pv_spec_t spec;
4943
0
  str s;
4944
4945
0
  if(in==NULL || in->s==NULL)
4946
0
  {
4947
0
    LM_ERR("bad parameters\n");
4948
0
    return NULL;
4949
0
  }
4950
4951
0
  p = in->s;
4952
0
  while(is_in_str(p, in))
4953
0
  {
4954
0
    while(is_in_str(p, in) && (is_ws(*p)||*p==','||*p==';'))
4955
0
      p++;
4956
0
    if(!is_in_str(p, in))
4957
0
    {
4958
0
      if(head==NULL)
4959
0
        LM_ERR("wrong item name list [%.*s]\n", in->len, in->s);
4960
0
      return head;
4961
0
    }
4962
0
    s.s=p;
4963
0
    s.len = in->s+in->len-p;
4964
0
    p = pv_parse_spec(&s, &spec);
4965
0
    if(p==NULL || (type && spec.type!=type))
4966
0
    {
4967
0
      LM_ERR("wrong item name list [%.*s]!\n", in->len, in->s);
4968
0
      goto error;
4969
0
    }
4970
0
    al = (pvname_list_t*)pkg_malloc(sizeof(pvname_list_t));
4971
0
    if(al==NULL)
4972
0
    {
4973
0
      LM_ERR("no more memory!\n");
4974
0
      goto error;
4975
0
    }
4976
0
    memset(al, 0, sizeof(pvname_list_t));
4977
0
    memcpy(&al->sname, &spec, sizeof(pv_spec_t));
4978
4979
0
    if(last==NULL)
4980
0
    {
4981
0
      head = al;
4982
0
      last = al;
4983
0
    } else {
4984
0
      last->next = al;
4985
0
      last = al;
4986
0
    }
4987
0
  }
4988
4989
0
  return head;
4990
4991
0
error:
4992
0
  while(head)
4993
0
  {
4994
0
    al = head;
4995
0
    head=head->next;
4996
0
    pkg_free(al);
4997
0
  }
4998
0
  return NULL;
4999
0
}
5000
5001
int pv_elem_free_all(pv_elem_p log)
5002
0
{
5003
0
  pv_elem_p t;
5004
0
  while(log)
5005
0
  {
5006
0
    t = log;
5007
0
    log = log->next;
5008
5009
0
    if (t->spec.trans)
5010
0
      free_transformation((trans_t *)t->spec.trans);
5011
0
    pkg_free(t);
5012
0
  }
5013
0
  return 0;
5014
0
}
5015
5016
static str pv_value_print(const pv_value_t *val)
5017
0
{
5018
0
  str printed = str_init(NULL);
5019
5020
0
  if (val->flags & PV_VAL_NULL)
5021
0
    return str_null;
5022
5023
0
  if (val->flags & PV_VAL_STR)
5024
0
    return val->rs;
5025
5026
0
  if (val->flags & (PV_VAL_INT|PV_TYPE_INT)) {
5027
0
    printed.s = int2str(val->ri, &printed.len);
5028
0
    return printed;
5029
0
  }
5030
5031
0
  LM_ERR("unknown type %x\n", val->flags);
5032
0
  return str_empty;
5033
0
}
5034
5035
void pv_value_destroy(pv_value_t *val)
5036
0
{
5037
0
  if(val==0) return;
5038
0
  if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
5039
0
  if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
5040
0
  memset(val, 0, sizeof(pv_value_t));
5041
0
}
5042
5043
/* IMPORTANT NOTE - even if the function prints and returns a static buffer, it
5044
 * has built-in support for PV_PRINTF_BUF_NO levels of nesting
5045
 * (or concurrent usage).  If you think it's not enough for you, either use
5046
 * pv_printf() directly, either increase PV_PRINT_BUF_NO   --bogdan */
5047
int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
5048
0
{
5049
0
  static int buf_itr = 0;
5050
5051
0
  if (list->next==0 && list->spec.getf==0) {
5052
0
    *s = list->text;
5053
0
    return 0;
5054
0
  } else {
5055
0
    *s = pv_print_buf[buf_itr];
5056
0
    buf_itr = (buf_itr + 1) % PV_PRINT_BUF_NO;
5057
0
    return pv_printf(msg, list, s->s, &s->len);
5058
0
  }
5059
0
}
5060
5061
void pv_spec_free(pv_spec_t *spec)
5062
0
{
5063
0
  if(spec==0) return;
5064
  /* TODO: free name if it is PV */
5065
0
  if(spec->trans)
5066
0
    free_transformation((trans_t*)spec->trans);
5067
0
  pkg_free(spec);
5068
0
}
5069
5070
int pv_spec_dbg(const pv_spec_p sp)
5071
0
{
5072
0
  if(sp==NULL)
5073
0
  {
5074
0
    LM_DBG("spec: <<NULL>>\n");
5075
0
    return 0;
5076
0
  }
5077
0
  LM_DBG("<spec>\n");
5078
0
  LM_DBG("type: %d\n", sp->type);
5079
0
  LM_DBG("getf: %p\n", sp->getf);
5080
0
  LM_DBG("setf: %p\n", sp->setf);
5081
0
  LM_DBG("tran: %p\n", sp->trans);
5082
0
  LM_DBG("<param>\n");
5083
0
  LM_DBG("<name>\n");
5084
0
  LM_DBG("type: %d\n", sp->pvp.pvn.type);
5085
0
  if(sp->pvp.pvn.type==PV_NAME_INTSTR)
5086
0
  {
5087
0
    LM_DBG("sub-type: %d\n", sp->pvp.pvn.u.isname.type);
5088
0
    if (sp->pvp.pvn.u.isname.type&AVP_NAME_STR)
5089
0
    {
5090
0
      LM_DBG("name str: %.*s\n",
5091
0
          sp->pvp.pvn.u.isname.name.s.len,
5092
0
          sp->pvp.pvn.u.isname.name.s.s);
5093
0
    } else {
5094
0
      LM_DBG("name in: %d\n",
5095
0
          sp->pvp.pvn.u.isname.name.n);
5096
0
    }
5097
5098
0
  } else if(sp->pvp.pvn.type==PV_NAME_PVAR) {
5099
0
    pv_spec_dbg((pv_spec_p)sp->pvp.pvn.u.dname);
5100
0
  } else {
5101
0
    LM_DBG("name: unknown\n");
5102
0
  }
5103
0
  LM_DBG("</name>\n");
5104
0
  LM_DBG("<index>\n");
5105
0
  LM_DBG("type: %d\n", sp->pvp.pvi.type);
5106
0
  if(sp->pvp.pvi.type==PV_IDX_INT)
5107
0
  {
5108
0
    LM_DBG("index: %d\n", sp->pvp.pvi.u.ival);
5109
0
  } else if(sp->pvp.pvi.type==PV_IDX_PVAR) {
5110
0
    pv_spec_dbg((pv_spec_p)sp->pvp.pvi.u.dval);
5111
0
  } else if(sp->pvp.pvi.type==PV_IDX_ALL){
5112
0
    LM_DBG("index: *\n");
5113
0
  } else {
5114
0
    LM_DBG("index: unknown\n");
5115
0
  }
5116
0
  LM_DBG("</index>\n");
5117
0
  LM_DBG("</param>\n");
5118
0
  LM_DBG("</spec\n");
5119
0
  return 0;
5120
0
}
5121
5122
5123
/**
5124
 *
5125
 */
5126
static int pv_init_extra_list(void)
5127
0
{
5128
0
  _pv_extra_list = (pv_extra_p*)pkg_malloc(sizeof(pv_extra_p));
5129
0
  if(_pv_extra_list==0)
5130
0
  {
5131
0
    LM_ERR("cannot alloc extra items list\n");
5132
0
    return -1;
5133
0
  }
5134
0
  *_pv_extra_list=0;
5135
0
  return 0;
5136
0
}
5137
5138
static int pv_add_extra(const pv_export_t *e)
5139
0
{
5140
0
  const char *p;
5141
0
  const str_const *in;
5142
0
  pv_extra_t *pvi = NULL;
5143
0
  pv_extra_t *pvj = NULL;
5144
0
  pv_extra_t *pvn = NULL;
5145
0
  int found;
5146
5147
0
  if(e==NULL || e->name.s==NULL || e->getf==NULL || e->type==PVT_NONE)
5148
0
  {
5149
0
    LM_ERR("invalid parameters\n");
5150
0
    return -1;
5151
0
  }
5152
5153
0
  if(_pv_extra_list==0)
5154
0
  {
5155
0
    LM_DBG("extra items list is not initialized\n");
5156
0
    if(pv_init_extra_list()!=0)
5157
0
    {
5158
0
      LM_ERR("cannot intit extra list\n");
5159
0
      return -1;
5160
0
    }
5161
0
  }
5162
0
  in = &(e->name);
5163
0
  p = in->s;
5164
0
  while(is_in_str(p,in) && is_pv_valid_char(*p))
5165
0
    p++;
5166
0
  if(is_in_str(p,in))
5167
0
  {
5168
0
    LM_ERR("invalid char [%c] in [%.*s]\n", *p, in->len, in->s);
5169
0
    return -1;
5170
0
  }
5171
0
  found = 0;
5172
0
  pvi = *_pv_extra_list;
5173
0
  while(pvi)
5174
0
  {
5175
0
    if(pvi->pve.name.len > in->len)
5176
0
      break;
5177
0
    if(pvi->pve.name.len==in->len)
5178
0
    {
5179
0
      found = strncmp(pvi->pve.name.s, in->s, in->len);
5180
0
      if(found>0)
5181
0
        break;
5182
0
      if(found==0)
5183
0
      {
5184
0
        LM_ERR("pvar [%.*s] already exists\n", in->len, in->s);
5185
0
        return -1;
5186
0
      }
5187
0
    }
5188
0
    pvj = pvi;
5189
0
    pvi = pvi->next;
5190
0
  }
5191
5192
0
  pvn = (pv_extra_t*)pkg_malloc(sizeof(pv_extra_t));
5193
0
  if(pvn==0)
5194
0
  {
5195
0
    LM_ERR("no more memory\n");
5196
0
    return -1;
5197
0
  }
5198
0
  memcpy(&pvn->pve, e, sizeof(*e));
5199
0
  pvn->pve.type += PVT_EXTRA;
5200
5201
0
  if(pvj==0)
5202
0
  {
5203
0
    pvn->next = *_pv_extra_list;
5204
0
    *_pv_extra_list = pvn;
5205
0
    goto done;
5206
0
  }
5207
0
  pvn->next = pvj->next;
5208
0
  pvj->next = pvn;
5209
5210
0
done:
5211
0
  return 0;
5212
0
}
5213
5214
int register_pvars_mod(const char *mod_name, const pv_export_t *items)
5215
0
{
5216
0
  int ret;
5217
0
  int i;
5218
5219
0
  if (items==0)
5220
0
    return 0;
5221
5222
0
  for ( i=0 ; items[i].name.s ; i++ ) {
5223
0
    ret = pv_add_extra(&items[i]);
5224
0
    if (ret!=0) {
5225
0
      LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
5226
0
          items[i].name.len, items[i].name.s, mod_name);
5227
0
    }
5228
0
  }
5229
0
  return 0;
5230
0
}
5231
5232
/**
5233
 *
5234
 */
5235
int pv_free_extra_list(void)
5236
0
{
5237
0
  pv_extra_p xe;
5238
0
  pv_extra_p xe1;
5239
0
  if(_pv_extra_list!=0)
5240
0
  {
5241
0
    xe = *_pv_extra_list;
5242
0
    while(xe!=0)
5243
0
    {
5244
0
      xe1 = xe;
5245
0
      xe = xe->next;
5246
0
      pkg_free(xe1);
5247
0
    }
5248
0
    pkg_free(_pv_extra_list);
5249
0
    _pv_extra_list = 0;
5250
0
  }
5251
5252
0
  return 0;
5253
0
}
5254
5255
static pv_context_t* new_pv_context(const str* name, pv_contextf_t get_context)
5256
0
{
5257
0
  pv_context_t* pvc_new = NULL;
5258
0
  int size;
5259
/*
5260
  if(get_context == NULL)
5261
  {
5262
    LM_ERR("NULL pointer to function\n");
5263
    return 0;
5264
  }
5265
*/
5266
0
  size = sizeof(pv_context_t) + name->len;
5267
0
  pvc_new = (pv_context_t*)pkg_malloc(size);
5268
0
  if(pvc_new == NULL)
5269
0
  {
5270
0
    LM_ERR("No more memory\n");
5271
0
    return 0;
5272
0
  }
5273
0
  memset(pvc_new, 0, size);
5274
5275
0
  pvc_new->name.s = (char*)pvc_new + sizeof(pv_context_t);
5276
0
  memcpy(pvc_new->name.s, name->s, name->len);
5277
0
  pvc_new->name.len = name->len;
5278
5279
0
  pvc_new->contextf = get_context;
5280
5281
0
  return pvc_new;
5282
0
}
5283
5284
int register_pv_context(char* cname, pv_contextf_t get_context)
5285
0
{
5286
0
  pv_context_t* pvc = pv_context_lst;
5287
0
  str name;
5288
5289
0
  if(cname == NULL)
5290
0
  {
5291
0
    LM_DBG("NULL parameter\n");
5292
0
    return -1;
5293
0
  }
5294
5295
0
  name.s = cname;
5296
0
  name.len = strlen(cname);
5297
5298
0
  LM_DBG("Registered new context: %.*s / %p\n", name.len, name.s, get_context);
5299
0
  pvc = pv_get_context(&name);
5300
0
  if(pvc == NULL)
5301
0
  {
5302
0
    LM_DBG("Context not found\n");
5303
0
    if(add_pv_context(&name, get_context) == NULL)
5304
0
    {
5305
0
      LM_ERR("Failed to add context\n");
5306
0
      return -1;
5307
0
    }
5308
0
    return 1;
5309
0
  }
5310
5311
0
  if(pvc->contextf!=NULL)
5312
0
  {
5313
0
    LM_ERR("Context already registered [%s]\n", cname);
5314
0
    return -1;
5315
0
  }
5316
0
  if(get_context == NULL)
5317
0
  {
5318
0
    LM_ERR("NULL context getter function\n");
5319
0
    return -1;
5320
0
  }
5321
0
  pvc->contextf= get_context;
5322
0
  return 1;
5323
0
}
5324
5325
5326
/* function to register a pv context getter */
5327
static pv_context_t* add_pv_context(const str* name, pv_contextf_t get_context)
5328
0
{
5329
0
  pv_context_t* pvc = pv_context_lst;
5330
0
  pv_context_t* pvc_new, *pvc_prev;
5331
5332
0
  if(pvc == NULL)
5333
0
  {
5334
0
    pvc_new = new_pv_context(name, get_context);
5335
0
    if(pvc_new == NULL)
5336
0
    {
5337
0
      LM_ERR("Failed to allocate context\n");
5338
0
      return 0;
5339
0
    }
5340
0
    pv_context_lst = pvc_new;
5341
0
    return pvc_new;
5342
0
  }
5343
5344
0
  while(pvc)
5345
0
  {
5346
0
    if(pvc->name.len == name->len && strncmp(pvc->name.s, name->s, name->len)==0)
5347
0
    {
5348
0
      LM_ERR("PV Context already registered [%.*s]\n", name->len, name->s);
5349
0
      return 0;
5350
0
    }
5351
0
    pvc_prev = pvc;
5352
0
    pvc = pvc->next;
5353
0
  }
5354
5355
0
  pvc_new = new_pv_context(name, get_context);
5356
0
  if(pvc_new == NULL)
5357
0
  {
5358
0
    LM_ERR("Failed to allocate context\n");
5359
0
    return 0;
5360
0
  }
5361
5362
0
  LM_DBG("Registered new context: %.*s\n", name->len, name->s);
5363
5364
0
  pvc_prev->next = pvc_new;
5365
5366
0
  return pvc_new;
5367
0
}
5368
5369
static pv_context_t* pv_get_context(const str* name)
5370
0
{
5371
0
  pv_context_t* pvc = pv_context_lst;
5372
5373
0
  while(pvc)
5374
0
  {
5375
0
    if(pvc->name.len == name->len &&
5376
0
        strncmp(pvc->name.s, name->s, name->len) == 0)
5377
0
    {
5378
0
      return pvc;
5379
0
    }
5380
0
    pvc = pvc->next;
5381
0
  }
5382
0
  return 0;
5383
0
}
5384
5385
static int pv_contextlist_check(void)
5386
0
{
5387
0
  pv_context_t* pvc = pv_context_lst;
5388
5389
0
  while(pvc)
5390
0
  {
5391
0
    if(pvc->contextf == NULL)
5392
0
      return -1;
5393
5394
0
    pvc = pvc->next;
5395
0
  }
5396
0
  pvc_before_check = 0;
5397
0
  return 0;
5398
0
}
5399
5400
/* argument options '-o' */
5401
argv_p argv_vars = NULL;
5402
5403
static argv_p search_argv(const str *name)
5404
0
{
5405
0
  argv_p it;
5406
5407
0
  for (it = argv_vars; it; it = it->next) {
5408
0
    if (it->name.len == name->len &&
5409
0
        !strncmp(it->name.s, name->s, name->len))
5410
0
      return it;
5411
0
  }
5412
0
  return 0;
5413
0
}
5414
5415
int add_arg_var(char *opt)
5416
0
{
5417
0
  char *eq;
5418
0
  str name;
5419
0
  argv_p new = NULL;
5420
5421
0
  if (!opt) {
5422
0
    LM_ERR("cannot receive null option\n");
5423
0
    return -1;
5424
0
  }
5425
5426
0
  eq = strchr(opt, '=');
5427
0
  if (!eq) {
5428
0
    LM_ERR("invalid option format - '=' char cannot be found\n");
5429
0
    return -1;
5430
0
  }
5431
0
  if (eq <= opt) {
5432
0
    LM_ERR("no option name specified\n");
5433
0
    return -1;
5434
0
  }
5435
5436
0
  name.s = opt;
5437
0
  name.len = eq - name.s;
5438
5439
  /* check for duplicate option name */
5440
0
  if (search_argv(&name)) {
5441
0
    LM_ERR("duplicate option name <%.*s>\n", name.len, name.s);
5442
0
    return -1;
5443
0
  }
5444
5445
0
  new = (argv_p)pkg_malloc(sizeof(argv_t));
5446
0
  if (!new) {
5447
0
    LM_ERR("no more pkg memory\n");
5448
0
    return -1;
5449
0
  }
5450
0
  memset(new, 0, sizeof(argv_t));
5451
5452
0
  new->name.s = name.s;
5453
0
  new->name.len = name.len;
5454
5455
0
  new->value.s = eq+1;
5456
0
  new->value.len = strlen(opt) + opt - new->value.s;
5457
5458
0
  if (!new->value.len)
5459
0
    new->value.s = 0;
5460
5461
0
  new->next = argv_vars;
5462
0
  argv_vars = new;
5463
5464
0
  LM_DBG("added argument name <%.*s> = <%.*s>\n",
5465
0
      name.len, name.s, new->value.len, new->value.s);
5466
0
  return 0;
5467
5468
0
}
5469
5470
static int pv_parse_argv_name(pv_spec_p sp, const str *in)
5471
0
{
5472
0
  argv_p v_arg;
5473
5474
0
  if(in==NULL || in->s==NULL || sp==NULL)
5475
0
    return -1;
5476
5477
0
  v_arg = search_argv(in);
5478
0
  if (!v_arg) {
5479
0
    LM_DBG("$argv(%.*s) not found\n", in->len, in->s);
5480
0
    sp->pvp.pvv.len = 0;
5481
0
    sp->pvp.pvv.s = 0;
5482
0
  } else {
5483
0
    sp->pvp.pvv = v_arg->value;
5484
0
    sp->pvp.pvn.u.isname.name.s = v_arg->name;
5485
0
  }
5486
5487
0
  sp->pvp.pvn.type = PV_NAME_PVAR;
5488
5489
0
  return 0;
5490
0
}
5491
5492
static int pv_get_argv(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
5493
0
{
5494
0
  if (!param) {
5495
0
    LM_ERR("null parameter received\n");
5496
0
    return -1;
5497
0
  }
5498
5499
0
  if (param->pvv.len == 0 || !param->pvv.s)
5500
0
    return pv_get_null(msg, param, res);
5501
5502
0
  return pv_get_strval(msg, param, res, &param->pvv);
5503
0
}
5504
5505
static int pv_parse_param_name(pv_spec_p sp, const str *in)
5506
0
{
5507
0
  char *p;
5508
0
  char *s;
5509
0
  pv_spec_p nsp = 0;
5510
5511
0
  if(in==NULL || in->s==NULL || sp==NULL)
5512
0
    return -1;
5513
0
  p = in->s;
5514
0
  if(*p==PV_MARKER)
5515
0
  {
5516
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
5517
0
    if(nsp==NULL)
5518
0
    {
5519
0
      LM_ERR("no more memory\n");
5520
0
      return -1;
5521
0
    }
5522
0
    s = pv_parse_spec(in, nsp);
5523
0
    if(s==NULL)
5524
0
    {
5525
0
      LM_ERR("invalid name [%.*s]\n", in->len, in->s);
5526
0
      pv_spec_free(nsp);
5527
0
      return -1;
5528
0
    }
5529
0
    sp->pvp.pvn.type = PV_NAME_PVAR;
5530
0
    sp->pvp.pvn.u.dname = (void*)nsp;
5531
0
    return 0;
5532
0
  }
5533
  /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
5534
  /* always an int type from now */
5535
0
  sp->pvp.pvn.u.isname.type = 0;
5536
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
5537
  /* do our best to convert it to an index */
5538
0
  if (str2int(in, (unsigned int *)&sp->pvp.pvn.u.isname.name.n) < 0)
5539
0
  {
5540
    /* remember it was a string, so we can retrieve it later */
5541
0
    sp->pvp.pvn.u.isname.name.s = *in;
5542
0
    sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
5543
0
  }
5544
0
  return 0;
5545
5546
0
}
5547
5548
static int pv_get_param(struct sip_msg *msg,  pv_param_t *ip, pv_value_t *res)
5549
0
{
5550
0
  if (!ip)
5551
0
  {
5552
0
    LM_ERR("null parameter received\n");
5553
0
    return -1;
5554
0
  }
5555
0
  return route_params_run(msg, ip, res);
5556
0
}
5557
5558
void destroy_argv_list(void)
5559
0
{
5560
0
  argv_p arg;
5561
5562
0
  while (argv_vars) {
5563
0
    arg = argv_vars;
5564
0
    argv_vars = argv_vars->next;
5565
0
    pkg_free(arg);
5566
0
  }
5567
0
}