Coverage Report

Created: 2025-03-14 06:13

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