Coverage Report

Created: 2026-04-12 06:51

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