Coverage Report

Created: 2025-07-18 06:32

/src/opensips/pvar.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Copyright (C) 2010-2020 OpenSIPS Solutions
3
 * Copyright (C) 2005-2009 Voice Sistem SRL
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * History:
23
 * --------
24
 * 2004-10-20 - added header name specifier (ramona)
25
 * 2005-06-14 - added avp name specifier (ramona)
26
 * 2005-06-18 - added color printing support via escape sequesnces
27
 *              contributed by Ingo Flaschberger (daniel)
28
 * 2005-06-22 - created this file from modules/xlog/pv_lib.c (daniel)
29
 * 2009-04-28 - $ct and $ct.fields() PVs added (bogdan)
30
 * 2009-05-02 - $branch() added, $br, $bR, $bf, $bF removed (bogdan)
31
 */
32
33
#include <stdio.h>
34
#include <string.h>
35
#include <time.h>
36
#include <sys/types.h>
37
#include <unistd.h>
38
39
#include "dprint.h"
40
#include "mem/mem.h"
41
#include "mem/shm_mem.h"
42
#include "ut.h"
43
#include "trim.h"
44
#include "dset.h"
45
#include "action.h"
46
#include "socket_info.h"
47
#include "route_struct.h"
48
#include "usr_avp.h"
49
#include "errinfo.h"
50
#include "transformations.h"
51
#include "script_var.h"
52
#include "pvar.h"
53
#include "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
static int pv_parse_socket_out_name(pv_spec_p sp, const str *in)
2466
0
{
2467
0
  if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
2468
0
    return -1;
2469
2470
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
2471
0
  sp->pvp.pvn.u.isname.type = 0;
2472
2473
0
  if (in->len==SOCK_FORCED_LEN &&
2474
0
  strncasecmp(in->s, SOCK_FORCED_S, SOCK_FORCED_LEN)==0 ) {
2475
0
    sp->pvp.pvn.u.isname.name.n = SOCK_FORCED_ID;
2476
0
    return 0;
2477
0
  } else {
2478
0
    return pv_parse_socket_name(sp, in);
2479
0
  }
2480
0
}
2481
2482
2483
static inline int get_socket_field( const struct socket_info *si,
2484
                      pv_name_t *pvn, pv_value_t *res)
2485
0
{
2486
0
  if (si==NULL)
2487
0
    return pv_get_null( NULL, NULL, res);
2488
2489
  /* return the field */
2490
0
  switch (pvn->u.isname.name.n) {
2491
0
    case 0: /* return full socket description */
2492
0
    case SOCK_FORCED_ID: /* return forced socket description */
2493
0
      res->rs = si->sock_str;
2494
0
      res->flags = PV_VAL_STR;
2495
0
      break;
2496
0
    case SOCK_IP_ID: /* return IP address */
2497
0
      res->rs = si->address_str;
2498
0
      res->flags = PV_VAL_STR;
2499
0
      break;
2500
0
    case SOCK_PORT_ID: /* return PORT */
2501
0
      res->rs = si->port_no_str;
2502
0
      res->ri = si->port_no;
2503
0
      res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
2504
0
      break;
2505
0
    case SOCK_PROTO_ID: /* return PROTOCOL */
2506
0
      if ( si->proto>=PROTO_FIRST && si->proto<PROTO_LAST &&
2507
0
      protos[si->proto].id ) {
2508
0
        res->rs.s = protos[si->proto].name;
2509
0
        res->rs.len = strlen(res->rs.s);
2510
0
        res->flags = PV_VAL_STR;
2511
0
      } else {
2512
0
        return pv_get_null( NULL, NULL, res);
2513
0
      }
2514
0
      break;
2515
0
    case SOCK_ADV_IP_ID: /* return advertised IP address */
2516
0
      if (si->adv_name_str.s) {
2517
0
        res->rs = si->adv_name_str;
2518
0
        res->flags = PV_VAL_STR;
2519
0
      } else {
2520
0
        return pv_get_null( NULL, NULL, res);
2521
0
      }
2522
0
      break;
2523
0
    case SOCK_ADV_PORT_ID: /* return advertised PORT */
2524
0
      if (si->adv_port_str.s) {
2525
0
        res->rs = si->adv_port_str;
2526
0
        res->ri = si->adv_port;
2527
0
        res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
2528
0
      } else {
2529
0
        return pv_get_null( NULL, NULL, res);
2530
0
      }
2531
0
      break;
2532
0
    case SOCK_TAG_ID: /* return internal TAG */
2533
0
      if (si->tag.s) {
2534
0
        res->rs = si->tag;
2535
0
        res->flags = PV_VAL_STR;
2536
0
      } else {
2537
0
        return pv_get_null( NULL, NULL, res);
2538
0
      }
2539
0
      break;
2540
0
    case SOCK_ANYCAST_ID: /* return ANYCAST */
2541
0
      if (si->flags&SI_IS_ANYCAST)
2542
0
        res->ri = 1;
2543
0
      else
2544
0
        res->ri = 0;
2545
0
      res->flags = PV_VAL_INT|PV_TYPE_INT;
2546
0
      break;
2547
0
    case SOCK_AF_ID:  /* returns Address Family */
2548
0
      if (si->address.af == AF_INET) {
2549
0
        res->rs.s = "INET";
2550
0
        res->rs.len = 4;
2551
0
      } else if (si->address.af == AF_INET6) {
2552
0
        res->rs.s = "INET6";
2553
0
        res->rs.len = 5;
2554
0
      } else
2555
0
        return pv_get_null( NULL, NULL, res);
2556
0
      res->flags = PV_VAL_STR;
2557
0
      break;
2558
0
    default:
2559
0
      LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.name.n);
2560
0
      return pv_get_null(NULL, NULL, res);
2561
0
  }
2562
0
  return 0;
2563
0
}
2564
2565
2566
static int pv_get_socket_in_fields(struct sip_msg *msg, pv_param_t *param,
2567
                              pv_value_t *res)
2568
0
{
2569
2570
0
  if(msg==NULL || res==NULL)
2571
0
    return -1;
2572
2573
0
  return get_socket_field( msg->rcv.bind_address, &param->pvn, res);
2574
0
}
2575
2576
2577
static int pv_get_socket_out_fields(struct sip_msg *msg, pv_param_t *param,
2578
                              pv_value_t *res)
2579
0
{
2580
0
  const struct socket_info *si;
2581
2582
0
  if(msg==NULL || res==NULL)
2583
0
    return -1;
2584
2585
0
  if (param->pvn.u.isname.name.n == SOCK_FORCED_ID && !msg->force_send_socket)
2586
0
    return pv_get_null(msg, NULL, res);
2587
2588
0
  si = (msg->force_send_socket) ?
2589
0
    msg->force_send_socket : msg->rcv.bind_address;
2590
2591
0
  return get_socket_field( si, &param->pvn, res);
2592
0
}
2593
2594
2595
2596
2597
/************************************************************/
2598
2599
/**
2600
 *
2601
 */
2602
static int pv_get_avp(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2603
0
{
2604
0
  unsigned short name_type;
2605
0
  int avp_name;
2606
0
  int_str avp_value;
2607
0
  struct usr_avp *avp;
2608
0
  int_str avp_value0;
2609
0
  struct usr_avp *avp0;
2610
0
  int idx;
2611
0
  int idxf;
2612
0
  char *p;
2613
0
  int n=0;
2614
2615
0
  if(msg==NULL || res==NULL || param==NULL)
2616
0
    return -1;
2617
2618
  /* get the name */
2619
0
  if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
2620
0
  {
2621
0
    LM_ERR("invalid name\n");
2622
0
    return -1;
2623
0
  }
2624
  /* get the index */
2625
0
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
2626
0
  {
2627
0
    LM_ERR("invalid index\n");
2628
0
    return -1;
2629
0
  }
2630
0
  if (idxf==PV_IDX_APPEND)
2631
0
    return pv_get_null(msg, param, res);
2632
2633
0
  if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0)
2634
0
    return pv_get_null(msg, param, res);
2635
0
  res->flags = PV_VAL_STR;
2636
2637
0
  if (idxf!=PV_IDX_ALL && idx==0)
2638
0
  {
2639
0
    if(avp->flags & AVP_VAL_STR) {
2640
0
      res->rs = avp_value.s;
2641
0
    } else if(avp->flags & AVP_VAL_NULL) {
2642
0
      res->flags |= PV_VAL_NULL;
2643
0
    } else {
2644
0
      res->rs.s = sint2str(avp_value.n, &res->rs.len);
2645
0
      res->ri = avp_value.n;
2646
0
      res->flags |= PV_VAL_INT|PV_TYPE_INT;
2647
0
    }
2648
0
    return 0;
2649
0
  }
2650
2651
  /* print the entire AVP array */
2652
0
  if(idxf==PV_IDX_ALL)
2653
0
  {
2654
0
    p = pv_local_buf;
2655
2656
    /* separately handle the first AVP */
2657
0
    if(avp->flags & AVP_VAL_STR) {
2658
0
      res->rs = avp_value.s;
2659
0
    } else if(avp->flags & AVP_VAL_NULL) {
2660
0
      memset(&res->rs, 0, sizeof res->rs);
2661
0
    } else {
2662
0
      res->rs.s = sint2str(avp_value.n, &res->rs.len);
2663
0
    }
2664
2665
0
    if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE)
2666
0
    {
2667
0
      LM_ERR("local buffer length exceeded!\n");
2668
0
      return pv_get_null(msg, param, res);
2669
0
    }
2670
0
    memcpy(p, res->rs.s, res->rs.len);
2671
0
    p += res->rs.len;
2672
2673
    /* print subsequent AVPs as [DELIM AVP]* */
2674
0
    while ((avp = search_first_avp(name_type, avp_name, &avp_value, avp)))
2675
0
    {
2676
0
      if(avp->flags & AVP_VAL_STR) {
2677
0
        res->rs = avp_value.s;
2678
0
      } else if(avp->flags & AVP_VAL_NULL) {
2679
0
        memset(&res->rs, 0, sizeof res->rs);
2680
0
      } else {
2681
0
        res->rs.s = sint2str(avp_value.n, &res->rs.len);
2682
0
      }
2683
2684
0
      if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE)
2685
0
      {
2686
0
        LM_ERR("local buffer length exceeded\n");
2687
0
        return pv_get_null(msg, param, res);
2688
0
      }
2689
0
      memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
2690
0
      p += PV_FIELD_DELIM_LEN;
2691
2692
0
      if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE)
2693
0
      {
2694
0
        LM_ERR("local buffer length exceeded!\n");
2695
0
        return pv_get_null(msg, param, res);
2696
0
      }
2697
0
      memcpy(p, res->rs.s, res->rs.len);
2698
0
      p += res->rs.len;
2699
0
    }
2700
2701
0
    *p = 0;
2702
0
    res->rs.s = pv_local_buf;
2703
0
    res->rs.len = p - pv_local_buf;
2704
0
    return 0;
2705
0
  }
2706
2707
  /* we have a numeric index */
2708
0
  if(idx<0)
2709
0
  {
2710
0
    n = 1;
2711
0
    avp0 = avp;
2712
0
    while ((avp0=search_first_avp(name_type, avp_name,
2713
0
            &avp_value0, avp0))!=0) n++;
2714
0
    idx = -idx;
2715
0
    if(idx>n)
2716
0
    {
2717
0
      LM_DBG("index out of range\n");
2718
0
      return pv_get_null(msg, param, res);
2719
0
    }
2720
0
    idx = n - idx;
2721
0
    if(idx==0)
2722
0
    {
2723
0
      if(avp->flags & AVP_VAL_STR) {
2724
0
        res->rs = avp_value.s;
2725
0
      } else if(avp->flags & AVP_VAL_NULL) {
2726
0
        res->flags |= PV_VAL_NULL;
2727
0
      } else {
2728
0
        res->rs.s = sint2str(avp_value.n, &res->rs.len);
2729
0
        res->ri = avp_value.n;
2730
0
        res->flags |= PV_VAL_INT|PV_TYPE_INT;
2731
0
      }
2732
0
      return 0;
2733
0
    }
2734
0
  }
2735
0
  n=0;
2736
0
  while(n<idx
2737
0
      && (avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0)
2738
0
    n++;
2739
2740
0
  if(avp!=0)
2741
0
  {
2742
0
    if(avp->flags & AVP_VAL_STR) {
2743
0
      res->rs = avp_value.s;
2744
0
    } else if(avp->flags & AVP_VAL_NULL) {
2745
0
      res->flags |= PV_VAL_NULL;
2746
0
    } else {
2747
0
      res->rs.s = sint2str(avp_value.n, &res->rs.len);
2748
0
      res->ri = avp_value.n;
2749
0
      res->flags |= PV_VAL_INT|PV_TYPE_INT;
2750
0
    }
2751
0
    return 0;
2752
0
  }
2753
2754
0
  LM_DBG("index out of range\n");
2755
0
  return pv_get_null(msg, param, res);
2756
0
}
2757
2758
2759
static int pv_resolve_hdr_name(const str *in, pv_value_t *tv)
2760
0
{
2761
0
  struct hdr_field hdr;
2762
0
  str s;
2763
0
  if(in->len>=PV_LOCAL_BUF_SIZE-1)
2764
0
  {
2765
0
    LM_ERR("name too long\n");
2766
0
    return -1;
2767
0
  }
2768
0
  memcpy(pv_local_buf, in->s, in->len);
2769
0
  pv_local_buf[in->len] = ':';
2770
0
  s.s = pv_local_buf;
2771
0
  s.len = in->len+1;
2772
2773
0
  if (parse_hname2(s.s, s.s + ((s.len<4)?4:s.len), &hdr)==0)
2774
0
  {
2775
0
    LM_ERR("error parsing header name [%.*s]\n", s.len, s.s);
2776
0
    return -1;
2777
0
  }
2778
0
  if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T)
2779
0
  {
2780
0
    LM_DBG("using hdr type (%d) instead of <%.*s>\n",
2781
0
      hdr.type, in->len, in->s);
2782
0
    tv->flags = 0;
2783
0
    tv->ri = hdr.type;
2784
0
  } else {
2785
0
    tv->flags = PV_VAL_STR;
2786
0
    tv->rs = *in;
2787
0
  }
2788
0
  return 0;
2789
0
}
2790
2791
static int pv_get_hdr_prolog(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res, pv_value_t* tv)
2792
0
{
2793
0
  if(msg==NULL || res==NULL || param==NULL)
2794
0
    return -1;
2795
2796
  /* get the name */
2797
0
  if(param->pvn.type == PV_NAME_PVAR)
2798
0
  {
2799
0
    if(pv_get_spec_name(msg, param, tv)!=0 || (!(tv->flags&PV_VAL_STR)))
2800
0
    {
2801
0
      LM_ERR("invalid name\n");
2802
0
      return -1;
2803
0
    }
2804
0
    if (pv_resolve_hdr_name(&tv->rs, tv) < 0)
2805
0
      return -1;
2806
0
  } else {
2807
0
    if(param->pvn.u.isname.type == AVP_NAME_STR)
2808
0
    {
2809
0
      tv->flags = PV_VAL_STR;
2810
0
      tv->rs = param->pvn.u.isname.name.s;
2811
0
    } else {
2812
0
      tv->flags = 0;
2813
0
      tv->ri = param->pvn.u.isname.name.n;
2814
0
    }
2815
0
  }
2816
  /* we need to be sure we have parsed all headers */
2817
0
  if(parse_headers(msg, HDR_EOH_F, 0)<0)
2818
0
  {
2819
0
    LM_ERR("error parsing headers\n");
2820
0
    return pv_get_null(msg, param, res);
2821
0
  }
2822
0
  return 1;
2823
0
}
2824
2825
static int pv_get_hdrcnt(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2826
0
{
2827
0
  pv_value_t tv;
2828
0
  struct hdr_field *hf;
2829
0
  unsigned int n;
2830
0
  int ret;
2831
2832
0
  if ( (ret=pv_get_hdr_prolog(msg,  param, res, &tv)) <= 0 )
2833
0
        return ret;
2834
2835
0
  n = 0;
2836
0
  if (tv.flags==0) {
2837
    /* it is a known header -> use type to find it */
2838
0
    for (hf=msg->headers; hf; hf=hf->next) {
2839
0
      if (tv.ri==hf->type)
2840
0
              ++n;
2841
0
    }
2842
0
  } else {
2843
    /* it is an un-known header -> use name to find it */
2844
0
    for (hf=msg->headers; hf; hf=hf->next) {
2845
0
      if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
2846
0
      && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
2847
0
        ++n;
2848
0
    }
2849
0
  }
2850
0
  return pv_get_uintval(msg, param, res, n);
2851
0
}
2852
2853
static int pv_get_hdr(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
2854
0
{
2855
0
  int idx;
2856
0
  int idxf;
2857
0
  pv_value_t tv;
2858
0
  struct hdr_field *hf;
2859
0
  struct hdr_field *hf0;
2860
0
  char *p;
2861
0
  int n;
2862
0
  int ret;
2863
2864
0
  if ( (ret=pv_get_hdr_prolog(msg,  param, res, &tv)) <= 0 )
2865
0
        return ret;
2866
2867
0
  if (tv.flags==0) {
2868
    /* it is a known header -> use type to find it */
2869
0
    for (hf=msg->headers; hf; hf=hf->next) {
2870
0
      if (tv.ri==hf->type)
2871
0
        break;
2872
0
    }
2873
0
  } else {
2874
    /* it is an un-known header -> use name to find it */
2875
0
    for (hf=msg->headers; hf; hf=hf->next) {
2876
0
      if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
2877
0
      && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
2878
0
        break;
2879
0
    }
2880
0
  }
2881
2882
0
  if(hf==NULL)
2883
0
    return pv_get_null(msg, param, res);
2884
  /* get the index */
2885
0
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
2886
0
  {
2887
0
    LM_ERR("invalid index\n");
2888
0
    return -1;
2889
0
  }
2890
2891
  /* get the value */
2892
0
  res->flags = PV_VAL_STR;
2893
0
  if(idxf!=PV_IDX_ALL && idx==0)
2894
0
  {
2895
0
    res->rs  = hf->body;
2896
0
    return 0;
2897
0
  }
2898
0
  if(idxf==PV_IDX_ALL)
2899
0
  {
2900
0
    p = pv_local_buf;
2901
0
    do {
2902
0
      if(p!=pv_local_buf)
2903
0
      {
2904
0
        if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE)
2905
0
        {
2906
0
          LM_ERR("local buffer length exceeded\n");
2907
0
          return pv_get_null(msg, param, res);
2908
0
        }
2909
0
        memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
2910
0
        p += PV_FIELD_DELIM_LEN;
2911
0
      }
2912
2913
0
      if(p-pv_local_buf+hf->body.len+1>PV_LOCAL_BUF_SIZE)
2914
0
      {
2915
0
        LM_ERR("local buffer length exceeded!\n");
2916
0
        return pv_get_null(msg, param, res);
2917
0
      }
2918
0
      memcpy(p, hf->body.s, hf->body.len);
2919
0
      p += hf->body.len;
2920
      /* next hf */
2921
0
      if (tv.flags==0) {
2922
        /* it is a known header -> use type to find it */
2923
0
        for (hf=hf->next ; hf; hf=hf->next) {
2924
0
          if (tv.ri==hf->type)
2925
0
            break;
2926
0
        }
2927
0
      } else {
2928
        /* it is an un-known header -> use name to find it */
2929
0
        for (hf=hf->next ; hf; hf=hf->next) {
2930
0
          if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
2931
0
          && strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
2932
0
            break;
2933
0
        }
2934
0
      }
2935
0
    } while (hf);
2936
0
    *p = 0;
2937
0
    res->rs.s = pv_local_buf;
2938
0
    res->rs.len = p - pv_local_buf;
2939
0
    return 0;
2940
0
  }
2941
2942
  /* we have a numeric index */
2943
0
  hf0 = 0;
2944
0
  if(idx<0)
2945
0
  {
2946
0
    n = 1;
2947
    /* count headers */
2948
0
    if (tv.flags==0 ) {
2949
      /* it is a known header -> use type to find it */
2950
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2951
0
        if (tv.ri==hf0->type)
2952
0
          n++;
2953
0
      }
2954
0
    } else {
2955
      /* it is an un-known header -> use name to find it */
2956
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2957
0
        if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len
2958
0
        && strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0)
2959
0
          n++;
2960
0
      }
2961
0
    }
2962
2963
0
    idx = -idx;
2964
0
    if(idx>n)
2965
0
    {
2966
0
      LM_DBG("index out of range\n");
2967
0
      return pv_get_null(msg, param, res);
2968
0
    }
2969
0
    idx = n - idx;
2970
0
    if(idx==0)
2971
0
    {
2972
0
      res->rs  = hf->body;
2973
0
      return 0;
2974
0
    }
2975
0
  }
2976
0
  n=0;
2977
0
  while(n<idx)
2978
0
  {
2979
0
    if (tv.flags==0) {
2980
      /* it is a known header -> use type to find it */
2981
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2982
0
        if (tv.ri==hf0->type) {
2983
0
          n++;
2984
0
          if(n==idx) break;
2985
0
        }
2986
0
      }
2987
0
    } else {
2988
      /* it is an un-known header -> use name to find it */
2989
0
      for (hf0=hf->next; hf0; hf0=hf0->next) {
2990
0
        if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len
2991
0
        && strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0) {
2992
0
          n++;
2993
0
          if(n==idx) break;
2994
0
        }
2995
0
      }
2996
0
    }
2997
0
    if(hf0==NULL)
2998
0
      break;
2999
0
  }
3000
3001
0
  if(hf0!=0)
3002
0
  {
3003
0
    res->rs  = hf0->body;
3004
0
    return 0;
3005
0
  }
3006
3007
0
  LM_DBG("index out of range\n");
3008
0
  return pv_get_null(msg, param, res);
3009
3010
0
}
3011
3012
static int pv_get_hdr_name(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
3013
0
{
3014
0
  int idx, idx_f;
3015
0
  struct hdr_field *hf;
3016
0
  char *p;
3017
0
  int n;
3018
3019
0
  if(msg==NULL || res==NULL || param==NULL)
3020
0
    return -1;
3021
3022
  /* get the index */
3023
0
  if (pv_get_spec_index(msg, param, &idx, &idx_f) != 0) {
3024
0
    LM_ERR("invalid index\n");
3025
0
    return -1;
3026
0
  }
3027
3028
  /* make sure we have parsed all the headers */
3029
0
  if (parse_headers(msg, HDR_EOH_F, 0) <0 ) {
3030
0
    LM_ERR("error parsing headers\n");
3031
0
    return pv_get_null(msg, param, res);
3032
0
  }
3033
3034
0
  res->flags = PV_VAL_STR;
3035
3036
0
  if (idx_f == PV_IDX_ALL) {
3037
    /* return all header names, separated by ',' */
3038
3039
0
    p = pv_local_buf;
3040
0
    hf = msg->headers;
3041
0
    do {
3042
0
      if (p != pv_local_buf) {
3043
0
        if (p - pv_local_buf + PV_FIELD_DELIM_LEN + 1 > PV_LOCAL_BUF_SIZE) {
3044
0
          LM_ERR("local buffer length exceeded\n");
3045
0
          return pv_get_null(msg, param, res);
3046
0
        }
3047
0
        memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
3048
0
        p += PV_FIELD_DELIM_LEN;
3049
0
      }
3050
3051
0
      if (p - pv_local_buf + hf->name.len + 1 > PV_LOCAL_BUF_SIZE) {
3052
0
        LM_ERR("local buffer length exceeded!\n");
3053
0
        return pv_get_null(msg, param, res);
3054
0
      }
3055
0
      memcpy(p, hf->name.s, hf->name.len);
3056
0
      p += hf->name.len;
3057
3058
0
      hf = hf->next;
3059
0
    } while (hf);
3060
3061
0
    *p = 0;
3062
0
    res->rs.s = pv_local_buf;
3063
0
    res->rs.len = p - pv_local_buf;
3064
0
    return 0;
3065
0
  }
3066
3067
0
  if (idx < 0) {
3068
    /* negative index, translate it to a positive one */
3069
3070
0
    n = 0;
3071
0
    for (hf = msg->headers; hf; hf = hf->next, n++) ;
3072
0
    idx = -idx;
3073
0
    if(idx > n) {
3074
0
      LM_DBG("index [%d] out of range\n", -idx);
3075
0
      return pv_get_null(msg, param, res);
3076
0
    }
3077
0
    idx = n - idx;
3078
0
  }
3079
3080
0
  for (hf = msg->headers, n = 0; hf && n != idx; hf = hf->next, n++) ;
3081
3082
0
  if (!hf) {
3083
0
    LM_DBG("index [%d] out of range\n", idx);
3084
0
    return pv_get_null(msg, param, res);
3085
0
  }
3086
3087
0
  res->rs = hf->name;
3088
0
  return 0;
3089
0
}
3090
3091
static int pv_get_scriptvar(struct sip_msg *msg,  pv_param_t *param,
3092
    pv_value_t *res)
3093
0
{
3094
0
  int ival = 0;
3095
0
  char *sval = NULL;
3096
0
  script_var_t *sv=NULL;
3097
3098
0
  if(msg==NULL || res==NULL)
3099
0
    return -1;
3100
3101
0
  if(param==NULL || param->pvn.u.dname==0)
3102
0
    return pv_get_null(msg, param, res);
3103
3104
0
  sv= (script_var_t*)param->pvn.u.dname;
3105
3106
0
  if (sv->v.flags&VAR_VAL_NULL)
3107
0
    return pv_get_null(msg, param, res);
3108
3109
0
  if(sv->v.flags&VAR_VAL_STR)
3110
0
  {
3111
0
    res->rs = sv->v.value.s;
3112
0
    res->flags = PV_VAL_STR;
3113
0
  } else {
3114
0
    sval = sint2str(sv->v.value.n, &ival);
3115
3116
0
    res->rs.s = sval;
3117
0
    res->rs.len = ival;
3118
3119
0
    res->ri = sv->v.value.n;
3120
0
    res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
3121
0
  }
3122
0
  return 0;
3123
0
}
3124
3125
/********* end PV get functions *********/
3126
3127
/********* start PV set functions *********/
3128
static int pv_set_avp(struct sip_msg* msg, pv_param_t *param,
3129
    int op, pv_value_t *val)
3130
0
{
3131
0
  int avp_name;
3132
0
  int_str avp_val;
3133
0
  int flags;
3134
0
  unsigned short name_type;
3135
0
  int idx, idxf;
3136
3137
0
  if(param==NULL)
3138
0
  {
3139
0
    LM_ERR("bad parameters\n");
3140
0
    return -1;
3141
0
  }
3142
3143
0
  if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
3144
0
  {
3145
0
    LM_ALERT("BUG in getting dst AVP name\n");
3146
0
    goto error;
3147
0
  }
3148
3149
  /* get the index */
3150
0
  if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
3151
0
  {
3152
0
    LM_ERR("invalid index\n");
3153
0
    return -1;
3154
0
  }
3155
3156
0
  if(val == NULL)
3157
0
  {
3158
0
    if(op == COLONEQ_T || idxf == PV_IDX_ALL)
3159
0
      destroy_avps(name_type, avp_name, 1);
3160
0
    else
3161
0
    {
3162
0
      destroy_index_avp(name_type, avp_name, idx);
3163
0
    }
3164
0
    return 0;
3165
0
  }
3166
3167
0
  if(op == COLONEQ_T || idxf == PV_IDX_ALL)
3168
0
    destroy_avps(name_type, avp_name, 1);
3169
3170
0
  flags = name_type;
3171
0
  if(val->flags&PV_TYPE_INT)
3172
0
  {
3173
0
    avp_val.n = val->ri;
3174
0
  } else {
3175
0
    avp_val.s = val->rs;
3176
0
    flags |= AVP_VAL_STR;
3177
0
  }
3178
3179
0
  if(idxf == PV_IDX_INT || idxf == PV_IDX_PVAR) /* if the avp is indexed */
3180
0
  {
3181
0
    if(replace_avp(flags, avp_name, avp_val, idx)< 0)
3182
0
    {
3183
0
      LM_ERR("Failed to replace avp\n");
3184
0
      goto error;
3185
0
    }
3186
0
  }
3187
0
  else if (idxf == PV_IDX_APPEND) /* add AVP at the end */
3188
0
  {
3189
0
    if (add_avp_last(flags, avp_name, avp_val)<0)
3190
0
    {
3191
0
      LM_ERR("error - cannot add AVP\n");
3192
0
      goto error;
3193
0
    }
3194
0
  }
3195
0
  else {
3196
0
    if (add_avp(flags, avp_name, avp_val)<0)
3197
0
    {
3198
0
      LM_ERR("error - cannot add AVP\n");
3199
0
      goto error;
3200
0
    }
3201
0
  }
3202
3203
0
  return 0;
3204
0
error:
3205
0
  return -1;
3206
0
}
3207
3208
static int pv_set_scriptvar(struct sip_msg* msg, pv_param_t *param,
3209
    int op, pv_value_t *val)
3210
0
{
3211
0
  int_str avp_val;
3212
0
  int flags;
3213
3214
0
  if(param==NULL)
3215
0
  {
3216
0
    LM_ERR("bad parameters\n");
3217
0
    return -1;
3218
0
  }
3219
3220
0
  if(param->pvn.u.dname==0)
3221
0
  {
3222
0
    LM_ERR("error - cannot find svar\n");
3223
0
    goto error;
3224
0
  }
3225
0
  if(val == NULL)
3226
0
  {
3227
0
    set_var_value((script_var_t*)param->pvn.u.dname, NULL, VAR_VAL_NULL);
3228
0
    return 0;
3229
0
  }
3230
0
  if(val->flags&PV_TYPE_INT)
3231
0
  {
3232
0
    avp_val.n = val->ri;
3233
0
    flags = 0;
3234
0
  } else {
3235
0
    avp_val.s = val->rs;
3236
0
    flags = VAR_VAL_STR;
3237
0
  }
3238
0
  if(set_var_value((script_var_t*)param->pvn.u.dname, &avp_val, flags)==NULL)
3239
0
  {
3240
0
    LM_ERR("error - cannot set svar [%.*s] \n",
3241
0
        ((script_var_t*)param->pvn.u.dname)->name.len,
3242
0
        ((script_var_t*)param->pvn.u.dname)->name.s);
3243
0
    goto error;
3244
0
  }
3245
0
  return 0;
3246
0
error:
3247
0
  return -1;
3248
0
}
3249
3250
static int pv_set_dsturi(struct sip_msg* msg, pv_param_t *param,
3251
    int op, pv_value_t *val)
3252
0
{
3253
0
  if(msg==NULL || param==NULL)
3254
0
  {
3255
0
    LM_ERR("bad parameters\n");
3256
0
    return -1;
3257
0
  }
3258
3259
0
  if(val == NULL)
3260
0
  {
3261
0
    reset_dst_uri(msg);
3262
3263
0
    return 1;
3264
0
  }
3265
0
  if(!(val->flags&PV_VAL_STR))
3266
0
  {
3267
0
    LM_ERR("error - str value required to set dst uri\n");
3268
0
    goto error;
3269
0
  }
3270
3271
0
  if(set_dst_uri(msg, &val->rs)!=0)
3272
0
    goto error;
3273
3274
0
  return 0;
3275
0
error:
3276
0
  return -1;
3277
0
}
3278
3279
static int pv_set_ruri(struct sip_msg* msg, pv_param_t *param,
3280
    int op, pv_value_t *val)
3281
0
{
3282
0
  if(msg==NULL || param==NULL || val==NULL)
3283
0
  {
3284
0
    LM_ERR("bad parameters\n");
3285
0
    return -1;
3286
0
  }
3287
3288
0
  if(!(val->flags&PV_VAL_STR))
3289
0
  {
3290
0
    LM_ERR("str value required to set R-URI\n");
3291
0
    goto error;
3292
0
  }
3293
3294
0
  if (set_ruri( msg, &val->rs)!=0) {
3295
0
    LM_ERR("failed to set RURI\n");
3296
0
    goto error;
3297
0
  }
3298
3299
0
  return 0;
3300
0
error:
3301
0
  return -1;
3302
0
}
3303
3304
static int pv_set_ru_q(struct sip_msg* msg, pv_param_t *param,
3305
    int op, pv_value_t *val)
3306
0
{
3307
0
  if(msg==NULL || param==NULL || val==NULL)
3308
0
  {
3309
0
    LM_ERR("bad parameters\n");
3310
0
    return -1;
3311
0
  }
3312
3313
0
  if(!(val->flags&PV_VAL_INT))
3314
0
  {
3315
0
    LM_ERR("int value required to set r-uri queue value\n");
3316
0
    return -1;
3317
0
  }
3318
3319
0
  if (val->ri > 1000) {
3320
0
    LM_WARN("queue value too big %d - setting queue to "
3321
0
        "maximum value (1000)\n", val->ri);
3322
0
    set_ruri_q(msg, 1000);
3323
0
  } else
3324
0
    set_ruri_q(msg, val->ri);
3325
3326
0
  return 0;
3327
0
}
3328
3329
static int pv_set_ruri_user(struct sip_msg* msg, pv_param_t *param,
3330
    int op, pv_value_t *val)
3331
0
{
3332
0
  str sval;
3333
3334
0
  if(msg==NULL || param==NULL)
3335
0
  {
3336
0
    LM_ERR("bad parameters\n");
3337
0
    return -1;
3338
0
  }
3339
3340
0
  if(val == NULL)
3341
0
    sval = str_empty;
3342
0
  else if(!(val->flags&PV_VAL_STR)) {
3343
0
    LM_ERR("str value required to set R-URI user\n");
3344
0
    return -1;
3345
0
  } else
3346
0
    sval = val->rs;
3347
3348
0
  if (rewrite_ruri(msg, &sval, 0, RW_RURI_USER) < 0) {
3349
0
    LM_ERR("Failed to set R-URI user\n");
3350
0
    return -1;
3351
0
  }
3352
3353
0
  return 0;
3354
0
}
3355
3356
static int pv_set_ruri_host(struct sip_msg* msg, pv_param_t *param,
3357
    int op, pv_value_t *val)
3358
0
{
3359
0
  if(msg==NULL || param==NULL || val==NULL)
3360
0
  {
3361
0
    LM_ERR("bad parameters\n");
3362
0
    return -1;
3363
0
  }
3364
3365
0
  if(!(val->flags&PV_VAL_STR))
3366
0
  {
3367
0
    LM_ERR("str value required to set R-URI hostname\n");
3368
0
    return -1;
3369
0
  }
3370
3371
0
  if (rewrite_ruri(msg, &val->rs, 0, RW_RURI_HOST) < 0) {
3372
0
    LM_ERR("Failed to set R-URI hostname\n");
3373
0
    return -1;
3374
0
  }
3375
3376
0
  return 0;
3377
0
}
3378
3379
static int pv_set_dsturi_host(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 DST-URI hostname\n");
3391
0
    return -1;
3392
0
  }
3393
3394
0
  if (set_dst_host_port(msg, &val->rs, NULL) < 0) {
3395
0
    LM_ERR("Failed to set DST-URI host\n");
3396
0
    return -1;
3397
0
  }
3398
3399
0
  return 0;
3400
0
}
3401
3402
static int pv_set_dsturi_port(struct sip_msg* msg, pv_param_t *param,
3403
    int op, pv_value_t *val)
3404
0
{
3405
0
  str sval;
3406
3407
0
  if(msg==NULL || param==NULL)
3408
0
  {
3409
0
    LM_ERR("bad parameters\n");
3410
0
    return -1;
3411
0
  }
3412
3413
0
  if(val == NULL)
3414
0
    sval = str_empty;
3415
0
  else if(!(val->flags&PV_VAL_STR))
3416
0
    sval.s = int2str(val->ri, &sval.len);
3417
0
  else
3418
0
    sval = val->rs;
3419
3420
0
  if (set_dst_host_port(msg, NULL, &sval) < 0) {
3421
0
    LM_ERR("Failed to set DST-URI port\n");
3422
0
    return -1;
3423
0
  }
3424
3425
0
  return 0;
3426
0
}
3427
3428
3429
3430
3431
static int pv_set_ruri_port(struct sip_msg* msg, pv_param_t *param,
3432
    int op, pv_value_t *val)
3433
0
{
3434
0
  str sval;
3435
3436
0
  if(msg==NULL || param==NULL)
3437
0
  {
3438
0
    LM_ERR("bad parameters\n");
3439
0
    return -1;
3440
0
  }
3441
3442
0
  if(val == NULL)
3443
0
    sval = str_empty;
3444
0
  else if(!(val->flags&PV_VAL_STR))
3445
0
    sval.s = int2str(val->ri, &sval.len);
3446
0
  else
3447
0
    sval = val->rs;
3448
3449
0
  if (rewrite_ruri(msg, &sval, 0, RW_RURI_PORT) < 0) {
3450
0
    LM_ERR("Failed to set R-URI hostname\n");
3451
0
    return -1;
3452
0
  }
3453
3454
0
  return 0;
3455
0
}
3456
3457
3458
static int pv_set_msg_branch(struct sip_msg* msg, pv_param_t *param,
3459
    int op, pv_value_t *val)
3460
0
{
3461
0
  struct msg_branch branch;
3462
3463
0
  if (msg==NULL || param==NULL) {
3464
0
    LM_ERR("bad parameters\n");
3465
0
    return -1;
3466
0
  }
3467
3468
0
  if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) ||
3469
0
  val->rs.len==0 ) {
3470
0
    LM_ERR("str value required to create a new branch\n");
3471
0
    return -1;
3472
0
  }
3473
3474
0
  memset( &branch, 0, sizeof branch);
3475
0
  branch.uri = val->rs;
3476
0
  branch.q = Q_UNSPECIFIED;
3477
0
  if (append_msg_branch( &branch )!=1){
3478
0
    LM_ERR("failed to append new branch\n");
3479
0
    return -1;
3480
0
  }
3481
3482
0
  return 0;
3483
0
}
3484
3485
3486
static int _int_pv_set_branch_fields(struct sip_msg* msg, pv_param_t *param,
3487
    int op, pv_value_t *val, int field, int has_ruri_branch)
3488
0
{
3489
0
  int size, is_ruri_branch = 0;
3490
0
  int idx;
3491
0
  int idxf;
3492
0
  str *s;
3493
0
  qvalue_t q;
3494
0
  unsigned int flags;
3495
0
  const struct socket_info *si;
3496
3497
0
  if (msg==NULL || param==NULL) {
3498
0
    LM_ERR("bad parameters\n");
3499
0
    return -1;
3500
0
  }
3501
3502
0
  if (msg->first_line.type == SIP_REPLY)
3503
0
    return -1;
3504
3505
  /* get the index */
3506
0
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
3507
0
    LM_ERR("invalid index\n");
3508
0
    return -1;
3509
0
  }
3510
3511
0
  if (idxf==PV_IDX_ALL) {
3512
0
    LM_ERR("SCRIPT BUG - * not allowed in branch assignment\n");
3513
0
    return -1;
3514
0
  }
3515
3516
0
  if (has_ruri_branch) {
3517
0
    size = get_dset_size() + 1 ;
3518
    /* no branch set, consider the last one */
3519
0
    if (idxf==0 && idx==0)
3520
0
      idx = size - 1;
3521
0
    else
3522
    /* if negative, count from the end */
3523
0
    if (idx<0)
3524
0
      idx = size + idx;
3525
    /* now evaluate and ajust the idx to dset only */
3526
0
    if (idx==0) {
3527
0
      is_ruri_branch = 1;
3528
0
    } else {
3529
      /* offset with -1 */
3530
0
      idx--;
3531
0
    }
3532
0
  } else {
3533
0
    size = get_dset_size();
3534
    /* if negative, count from the end */
3535
0
    if (idx<0)
3536
0
      idx = size + idx;
3537
0
  }
3538
3539
0
  if (!is_ruri_branch) {
3540
    /* if not RURI branch, it is a msg branch, so check the idx*/
3541
0
    if (idx<0 || idx>=get_dset_size()) {
3542
0
      LM_ERR("inexisting branch assignment [%d/%d]\n", size, idx);
3543
0
      return -1;
3544
0
    }
3545
0
  }
3546
3547
0
  switch (field) {
3548
0
    case BR_URI_ID: /* set URI */
3549
0
      if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) ||
3550
0
      val->rs.len==0 ) {
3551
0
        LM_ERR("str value required to set the branch URI\n");
3552
0
        return -1;
3553
0
      }
3554
0
      s = &val->rs;
3555
0
      return is_ruri_branch ?
3556
0
        set_ruri( msg, s) :
3557
0
        update_msg_branch_uri( idx, s);
3558
0
    case BR_Q_ID: /* set Q */
3559
0
      if ( val && !(val->flags&PV_VAL_INT) ) {
3560
0
        LM_ERR("INT value required to set the branch Q\n");
3561
0
        return -1;
3562
0
      }
3563
0
      q = (!val||val->flags&PV_VAL_NULL)? Q_UNSPECIFIED : val->ri;
3564
0
      if (is_ruri_branch )
3565
0
        set_ruri_q( msg, q);
3566
0
      else
3567
0
        update_msg_branch_q( idx, q);
3568
0
      return 0;
3569
0
    case BR_DURI_ID: /* set DURI */
3570
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3571
0
        LM_ERR("STR value required to set the branch DURI\n");
3572
0
        return -1;
3573
0
      }
3574
0
      s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs;
3575
0
      return is_ruri_branch ?
3576
0
        set_dst_uri( msg, s) :
3577
0
        update_msg_branch_dst_uri( idx, s);
3578
0
    case BR_PATH_ID: /* set PATH */
3579
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3580
0
        LM_ERR("STR value required to set the branch PATH\n");
3581
0
        return -1;
3582
0
      }
3583
0
      s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs;
3584
0
      return is_ruri_branch ?
3585
0
        set_path_vector( msg, s) :
3586
0
        update_msg_branch_path( idx, s);
3587
0
    case BR_FLAGS_ID: /* set FLAGS */
3588
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3589
0
        LM_ERR("string value required to set the branch FLAGS\n");
3590
0
        return -1;
3591
0
      }
3592
0
      flags = (!val||val->flags&PV_VAL_NULL)?
3593
0
        0 : flag_list_to_bitmask(str2const(&val->rs), FLAG_TYPE_BRANCH, FLAG_DELIM, 0);
3594
0
      if ( is_ruri_branch )
3595
0
        msg->ruri_bflags = flags;
3596
0
      else
3597
0
        update_msg_branch_bflags( idx, flags);
3598
0
      return 0;
3599
0
    case BR_SOCKET_ID: /* set SOCKET */
3600
0
      if ( val && !(val->flags&PV_VAL_STR) ) {
3601
0
        LM_ERR("STR value required to set the branch SOCKET\n");
3602
0
        return -1;
3603
0
      }
3604
0
      if (!val || val->flags&PV_VAL_NULL) {
3605
0
        si = NULL;
3606
0
      } else {
3607
0
        si = parse_sock_info(&val->rs);
3608
0
        if (si==NULL)
3609
0
          return -1;
3610
0
      }
3611
0
      if ( is_ruri_branch )
3612
0
        msg->force_send_socket = si;
3613
0
      else
3614
0
        update_msg_branch_socket( idx, si);
3615
0
      return 0;
3616
0
    default:
3617
0
      LM_CRIT("BUG - unsupported ID %d\n", field);
3618
0
      return -1;
3619
0
  }
3620
0
}
3621
3622
static int pv_set_branch_fields(struct sip_msg* msg, pv_param_t *param,
3623
    int op, pv_value_t *val)
3624
0
{
3625
  /* named branch fields,
3626
   * so the type is in the name, no RURI branch support*/
3627
0
  return _int_pv_set_branch_fields( msg, param, op, val,
3628
0
    param->pvn.u.isname.name.n, 0);
3629
0
}
3630
3631
static int pv_set_msg_branch_uri(struct sip_msg* msg, pv_param_t *param,
3632
    int op, pv_value_t *val)
3633
0
{
3634
0
  return _int_pv_set_branch_fields( msg, param, op, val, BR_URI_ID, 1);
3635
0
}
3636
3637
static int pv_set_msg_branch_duri(struct sip_msg* msg, pv_param_t *param,
3638
    int op, pv_value_t *val)
3639
0
{
3640
0
  return _int_pv_set_branch_fields( msg, param, op, val, BR_DURI_ID, 1);
3641
0
}
3642
3643
static int pv_set_msg_branch_q(struct sip_msg* msg, pv_param_t *param,
3644
    int op, pv_value_t *val)
3645
0
{
3646
0
  return _int_pv_set_branch_fields( msg, param, op, val, BR_Q_ID, 1);
3647
0
}
3648
3649
static int pv_set_msg_branch_path(struct sip_msg* msg, pv_param_t *param,
3650
    int op, pv_value_t *val)
3651
0
{
3652
0
  return _int_pv_set_branch_fields( msg, param, op, val, BR_PATH_ID, 1);
3653
0
}
3654
3655
static int pv_set_msg_branch_flags(struct sip_msg* msg, pv_param_t *param,
3656
    int op, pv_value_t *val)
3657
0
{
3658
0
  return _int_pv_set_branch_fields( msg, param, op, val, BR_FLAGS_ID, 1);
3659
0
}
3660
3661
static int pv_set_msg_branch_sock(struct sip_msg* msg, pv_param_t *param,
3662
    int op, pv_value_t *val)
3663
0
{
3664
0
  return _int_pv_set_branch_fields( msg, param, op, val, BR_SOCKET_ID, 1);
3665
0
}
3666
3667
static int pv_set_msg_branch_attr(struct sip_msg* msg, pv_param_t *param,
3668
    int op, pv_value_t *val)
3669
0
{
3670
0
  int idx, idxf;
3671
0
  int size, n, attr_name;
3672
0
  unsigned short attr_flags;
3673
0
  int_str attr_val;
3674
3675
0
  if (msg==NULL || param==NULL) {
3676
0
    LM_ERR("bad parameters\n");
3677
0
    return -1;
3678
0
  }
3679
3680
0
  if (msg->first_line.type == SIP_REPLY)
3681
0
    return -1;
3682
3683
0
  if(pv_get_avp_name(msg, param, &attr_name, &attr_flags)!=0) {
3684
0
    LM_ALERT("BUG in getting dst AVP name\n");
3685
0
    return -1;
3686
0
  }
3687
3688
  /* get the index */
3689
0
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
3690
0
    LM_ERR("invalid index\n");
3691
0
    return -1;
3692
0
  }
3693
3694
0
  if(idxf==PV_IDX_ALL) {
3695
0
    LM_ERR("SCRIPT BUG - * not allowed in branch assignment\n");
3696
0
    return -1;
3697
0
  }
3698
3699
0
  size = get_dset_size() + 1 /* ruri branch*/;
3700
  /* if no branch set, consider the last one */
3701
0
  if (idxf==0 && idx==0)
3702
0
    idx = size - 1;
3703
3704
  /* numerical index */
3705
0
  if (idx<0) {
3706
    /* index from the end */
3707
0
    if (-idx > size)
3708
0
      return -1;
3709
0
    idx = size + idx;
3710
0
  }
3711
3712
0
  if (!val || val->flags&PV_VAL_NULL) {
3713
0
    attr_val.n = 0; //useless, makes compiler happy
3714
0
    attr_flags |= AVP_VAL_NULL;
3715
0
  } else
3716
0
  if(val->flags&PV_TYPE_INT) {
3717
0
    attr_val.n = val->ri;
3718
0
  } else {
3719
0
    attr_val.s = val->rs;
3720
0
    attr_flags |= AVP_VAL_STR;
3721
0
  }
3722
3723
0
  n = set_msg_branch_attr(idx, attr_name, attr_flags, attr_val);
3724
3725
0
  return (n>=0) ? 0 : -1 ;
3726
0
}
3727
3728
3729
static int pv_set_force_sock(struct sip_msg* msg, pv_param_t *param,
3730
    int op, pv_value_t *val)
3731
0
{
3732
0
  const struct socket_info *si;
3733
3734
0
  if(msg==NULL || param==NULL)
3735
0
  {
3736
0
    LM_ERR("bad parameters\n");
3737
0
    return -1;
3738
0
  }
3739
3740
0
  if(val==NULL)
3741
0
  {
3742
0
    msg->force_send_socket = NULL;
3743
0
    return 0;
3744
0
  }
3745
3746
0
  if(!(val->flags&PV_VAL_STR) || val->rs.len<=0)
3747
0
  {
3748
0
    LM_ERR("str value required to set the force send sock\n");
3749
0
    goto error;
3750
0
  }
3751
3752
0
  si = parse_sock_info(&val->rs);
3753
0
  if (si!=NULL)
3754
0
  {
3755
0
    msg->force_send_socket = si;
3756
0
  } else {
3757
0
    LM_WARN("no socket found to match [%.*s]\n",
3758
0
        val->rs.len, val->rs.s);
3759
0
  }
3760
3761
0
  return 0;
3762
0
error:
3763
0
  return -1;
3764
0
}
3765
3766
3767
/********* end PV set functions *********/
3768
3769
static int pv_parse_scriptvar_name(pv_spec_p sp, const str *in)
3770
0
{
3771
0
  if(in==NULL || in->s==NULL || sp==NULL)
3772
0
    return -1;
3773
3774
0
  sp->pvp.pvn.type = PV_NAME_PVAR;
3775
0
  sp->pvp.pvn.u.dname = (void*)add_var(in);
3776
0
  if(sp->pvp.pvn.u.dname==NULL)
3777
0
  {
3778
0
    LM_ERR("cannot register var [%.*s]\n", in->len, in->s);
3779
0
    return -1;
3780
0
  }
3781
0
  return 0;
3782
0
}
3783
3784
static int pv_parse_hdr_name(pv_spec_p sp, const str *in)
3785
0
{
3786
0
  char *p;
3787
0
  pv_spec_p nsp = 0;
3788
0
  pv_value_t tv;
3789
3790
0
  if(in==NULL || in->s==NULL || sp==NULL)
3791
0
    return -1;
3792
3793
0
  p = in->s;
3794
0
  if(*p==PV_MARKER)
3795
0
  {
3796
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
3797
0
    if(nsp==NULL)
3798
0
    {
3799
0
      LM_ERR("no more memory\n");
3800
0
      return -1;
3801
0
    }
3802
0
    p = pv_parse_spec(in, nsp);
3803
0
    if(p==NULL)
3804
0
    {
3805
0
      LM_ERR("invalid name [%.*s]\n", in->len, in->s);
3806
0
      pv_spec_free(nsp);
3807
0
      return -1;
3808
0
    }
3809
    //LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
3810
    //pv_print_spec(nsp);
3811
0
    sp->pvp.pvn.type = PV_NAME_PVAR;
3812
0
    sp->pvp.pvn.u.dname = (void*)nsp;
3813
0
    return 0;
3814
0
  }
3815
3816
0
  if (pv_resolve_hdr_name(in, &tv) < 0)
3817
0
    return -1;
3818
3819
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3820
0
  if (!tv.flags)
3821
0
  {
3822
0
    LM_DBG("using hdr type (%d) instead of <%.*s>\n",
3823
0
      tv.ri, in->len, in->s);
3824
0
    sp->pvp.pvn.u.isname.type = 0;
3825
0
    sp->pvp.pvn.u.isname.name.n = tv.ri;
3826
0
  } else {
3827
0
    sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
3828
0
    sp->pvp.pvn.u.isname.name.s = *in;
3829
0
  }
3830
0
  return 0;
3831
0
}
3832
3833
int pv_parse_avp_name(pv_spec_p sp, const str *in)
3834
0
{
3835
0
  char *p;
3836
0
  char *s;
3837
0
  pv_spec_p nsp = 0;
3838
3839
0
  if(in==NULL || in->s==NULL || sp==NULL)
3840
0
    return -1;
3841
0
  p = in->s;
3842
0
  if(*p==PV_MARKER)
3843
0
  {
3844
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
3845
0
    if(nsp==NULL)
3846
0
    {
3847
0
      LM_ERR("no more memory\n");
3848
0
      return -1;
3849
0
    }
3850
0
    s = pv_parse_spec(in, nsp);
3851
0
    if(s==NULL)
3852
0
    {
3853
0
      LM_ERR("invalid name [%.*s]\n", in->len, in->s);
3854
0
      pv_spec_free(nsp);
3855
0
      return -1;
3856
0
    }
3857
    //LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
3858
    //pv_print_spec(nsp);
3859
0
    sp->pvp.pvn.type = PV_NAME_PVAR;
3860
0
    sp->pvp.pvn.u.dname = (void*)nsp;
3861
0
    return 0;
3862
0
  }
3863
  /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
3864
  /* always an int type from now */
3865
0
  sp->pvp.pvn.u.isname.type = 0;
3866
0
  if(parse_avp_spec(in, &sp->pvp.pvn.u.isname.name.n)!=0)
3867
0
  {
3868
0
    LM_ERR("bad avp name [%.*s]\n", in->len, in->s);
3869
0
    return -1;
3870
0
  }
3871
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3872
0
  return 0;
3873
0
}
3874
3875
static int pv_parse_avp_index(pv_spec_p sp, const str *in)
3876
0
{
3877
0
  #define AVP_APPEND_IDX "append"
3878
3879
0
  if(in==NULL || in->s==NULL || sp==NULL)
3880
0
    return -1;
3881
3882
0
  if ( (in->len==(sizeof(AVP_APPEND_IDX)-1)) &&
3883
0
  strncasecmp(in->s,AVP_APPEND_IDX,in->len)==0) {
3884
0
    sp->pvp.pvi.type = PV_IDX_APPEND;
3885
0
    return 0;
3886
0
  }
3887
0
  return pv_parse_index(sp,in);
3888
0
}
3889
3890
int pv_parse_index(pv_spec_p sp, const str *in)
3891
0
{
3892
0
  char *p;
3893
0
  char *s;
3894
0
  int sign;
3895
0
  pv_spec_p nsp = 0;
3896
3897
0
  if(in==NULL || in->s==NULL || sp==NULL)
3898
0
    return -1;
3899
0
  p = in->s;
3900
0
  if(*p==PV_MARKER)
3901
0
  {
3902
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
3903
0
    if(nsp==NULL)
3904
0
    {
3905
0
      LM_ERR("no more memory\n");
3906
0
      return -1;
3907
0
    }
3908
0
    memset(nsp, 0, sizeof(pv_spec_t));
3909
0
    s = pv_parse_spec(in, nsp);
3910
0
    if(s==NULL)
3911
0
    {
3912
0
      LM_ERR("invalid index [%.*s]\n", in->len, in->s);
3913
0
      pv_spec_free(nsp);
3914
0
      return -1;
3915
0
    }
3916
0
    sp->pvp.pvi.type = PV_IDX_PVAR;
3917
0
    sp->pvp.pvi.u.dval = (void*)nsp;
3918
0
    return 0;
3919
0
  }
3920
0
  if(*p=='*' && in->len==1)
3921
0
  {
3922
0
    sp->pvp.pvi.type = PV_IDX_ALL;
3923
0
    return 0;
3924
0
  }
3925
0
  sign = 1;
3926
0
  if(*p=='-')
3927
0
  {
3928
0
    sign = -1;
3929
0
    p++;
3930
0
  }
3931
0
  sp->pvp.pvi.u.ival = 0;
3932
0
  while(p<in->s+in->len && *p>='0' && *p<='9')
3933
0
  {
3934
0
    sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0';
3935
0
    p++;
3936
0
  }
3937
0
  if(p!=in->s+in->len)
3938
0
  {
3939
0
    LM_ERR("invalid index [%.*s]\n", in->len, in->s);
3940
0
    return -1;
3941
0
  }
3942
0
  sp->pvp.pvi.u.ival *= sign;
3943
0
  sp->pvp.pvi.type = PV_IDX_INT;
3944
3945
0
  return 0;
3946
0
}
3947
3948
int pv_init_iname(pv_spec_p sp, int param)
3949
0
{
3950
0
  if(sp==NULL)
3951
0
    return -1;
3952
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
3953
0
  sp->pvp.pvn.u.isname.name.n = param;
3954
0
  return 0;
3955
0
}
3956
3957
0
static int pv_get_line_number(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res){
3958
0
  int l;
3959
0
  char *ch;
3960
3961
0
  if (param==NULL) {
3962
0
    LM_CRIT("BUG - bad parameters\n");
3963
0
    return -1;
3964
0
  }
3965
3966
0
  if(res == NULL) {
3967
0
    return -1;
3968
0
  }
3969
3970
0
  res->ri = curr_action_line;
3971
0
  ch = int2str( (unsigned long)res->ri, &l);
3972
3973
0
  res->rs.s = ch;
3974
0
  res->rs.len = l;
3975
3976
0
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
3977
3978
0
  return 0;
3979
0
}
3980
3981
0
static int pv_get_cfg_file_name(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res){
3982
3983
0
  if (param==NULL) {
3984
0
    LM_CRIT("BUG - bad parameters\n");
3985
0
    return -1;
3986
0
  }
3987
3988
0
  if(res == NULL) {
3989
0
    return -1;
3990
0
  }
3991
3992
0
  res->rs.s = curr_action_file;
3993
0
  res->rs.len = (res->rs.s)?(strlen(res->rs.s)):(0);
3994
3995
0
  res->flags = PV_VAL_STR;
3996
3997
0
  return 0;
3998
0
}
3999
4000
4001
static int pv_set_log_level(struct sip_msg* msg, pv_param_t *param, int op,
4002
                              pv_value_t *val)
4003
0
{
4004
0
  if(param==NULL)
4005
0
  {
4006
0
    LM_ERR("bad parameters\n");
4007
0
    return -1;
4008
0
  }
4009
4010
0
  if(val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0) {
4011
    /* reset the value to default */
4012
0
    reset_proc_log_level();
4013
0
  } else {
4014
0
    if ((val->flags&PV_TYPE_INT)==0) {
4015
0
      LM_ERR("input for $log_level found not to be an integer\n");
4016
0
      return -1;
4017
0
    }
4018
0
    set_proc_log_level(val->ri);
4019
0
  }
4020
4021
0
  return 0;
4022
0
}
4023
4024
static int pv_get_log_level(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
4025
0
{
4026
0
  int l;
4027
4028
0
  if (param==NULL) {
4029
0
    LM_CRIT("BUG - bad parameters\n");
4030
0
    return -1;
4031
0
  }
4032
4033
0
  if(res == NULL) {
4034
0
    return -1;
4035
0
  }
4036
4037
0
  res->ri = *log_level;
4038
0
  res->rs.s = sint2str( (long)res->ri, &l);
4039
0
  res->rs.len = l;
4040
4041
0
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
4042
4043
0
  return 0;
4044
0
}
4045
4046
static int pv_set_xlog_level(struct sip_msg* msg, pv_param_t *param, int op,
4047
                              pv_value_t *val)
4048
0
{
4049
0
  if(param==NULL)
4050
0
  {
4051
0
    LM_ERR("bad parameters\n");
4052
0
    return -1;
4053
0
  }
4054
4055
0
  if(val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0) {
4056
    /* reset the value to default */
4057
0
    reset_xlog_level();
4058
0
  } else {
4059
0
    if ((val->flags&PV_TYPE_INT)==0) {
4060
0
      LM_ERR("input for $xlog_level found not to be an integer\n");
4061
0
      return -1;
4062
0
    }
4063
0
    set_local_xlog_level( val->ri );
4064
0
  }
4065
4066
0
  return 0;
4067
0
}
4068
4069
static int pv_get_xlog_level(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
4070
0
{
4071
0
  int l;
4072
4073
0
  if (param==NULL) {
4074
0
    LM_CRIT("BUG - bad parameters\n");
4075
0
    return -1;
4076
0
  }
4077
4078
0
  if(res == NULL) {
4079
0
    return -1;
4080
0
  }
4081
4082
0
  res->ri = *xlog_level;
4083
0
  res->rs.s = sint2str( (long)res->ri, &l);
4084
0
  res->rs.len = l;
4085
4086
0
  res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
4087
4088
0
  return 0;
4089
0
}
4090
4091
static int pv_get_return_value(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
4092
0
{
4093
0
  int index;
4094
0
  pv_value_t tv;
4095
4096
0
  if (param==NULL) {
4097
0
    LM_CRIT("BUG - bad parameters\n");
4098
0
    return -1;
4099
0
  }
4100
4101
0
  if(res == NULL)
4102
0
    return -1;
4103
4104
0
  if (param->pvn.type == PV_NAME_INTSTR) {
4105
0
    if (param->pvn.u.isname.type != 0) {
4106
0
      LM_ERR("route $return variable accepts only integer indexes\n");
4107
0
      return -1;
4108
0
    }
4109
0
    index = param->pvn.u.isname.name.n;
4110
0
  } else {
4111
    /* pvar -> it might be another $param variable! */
4112
0
    if(pv_get_spec_value(msg, (pv_spec_p)(param->pvn.u.dname), &tv)!=0) {
4113
0
      LM_ERR("cannot get spec value\n");
4114
0
      return -1;
4115
0
    }
4116
4117
0
    if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY) {
4118
0
      LM_ERR("null or empty name\n");
4119
0
      return -1;
4120
0
    }
4121
0
    if (!(tv.flags&PV_VAL_INT) || str2int(&tv.rs,(unsigned int*)&index) < 0) {
4122
0
      LM_ERR("invalid index <%.*s>\n", tv.rs.len, tv.rs.s);
4123
0
      return -1;
4124
0
    }
4125
0
  }
4126
4127
0
  if (script_return_get(res, index) < 0) {
4128
0
    LM_ERR("could not get return %d\n", index);
4129
0
    return -1;
4130
0
  }
4131
4132
  /* "normalize" integer */
4133
0
  if ((res->flags & PV_VAL_INT) && !(res->flags & PV_VAL_STR)) {
4134
0
    res->rs.s = int2str(res->ri, &res->rs.len);
4135
0
    res->flags |= PV_VAL_STR;
4136
0
  }
4137
4138
0
  return 0;
4139
0
}
4140
4141
/************** Boolean consts *****************/
4142
4143
const pv_value_t pv_true = {
4144
  .ri = 1,
4145
  .rs = str_init("true"),
4146
  .flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT,
4147
};
4148
4149
4150
const pv_value_t pv_false = {
4151
  .ri = 0,
4152
  .rs = str_init("false"),
4153
  .flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT,
4154
};
4155
4156
4157
/************** MSG FLAGS function *****************/
4158
4159
static int msg_flag_parse_name(pv_spec_p sp, const str *in)
4160
0
{
4161
0
  unsigned int idx;
4162
0
  if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
4163
0
    return -1;
4164
4165
0
  if ( (idx=fixup_flag(FLAG_TYPE_MSG, in))==NAMED_FLAG_ERROR) {
4166
0
    LM_ERR("failed to fix the flag <%.*s>\n",in->len,in->s);
4167
0
    return -1;
4168
0
  }
4169
4170
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
4171
0
  sp->pvp.pvn.u.isname.type = 0;
4172
4173
0
  sp->pvp.pvn.u.isname.name.n = idx;
4174
4175
0
  return 0;
4176
0
}
4177
4178
4179
static int msg_flag_set(struct sip_msg* msg, pv_param_t *param, int op,
4180
                              pv_value_t *val)
4181
0
{
4182
0
  if(param==NULL) {
4183
0
    LM_ERR("bad parameters\n");
4184
0
    return -1;
4185
0
  }
4186
4187
0
  if (val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0 ||
4188
0
  (val->flags&PV_TYPE_INT)==0 ) {
4189
0
    LM_ERR("input for $msg.flag() found not to be an integer\n");
4190
0
    return -1;
4191
0
  }
4192
4193
0
  if (val->ri==0)
4194
0
    resetflag (msg, (unsigned int)param->pvn.u.isname.name.n);
4195
0
  else
4196
0
    setflag( msg, (unsigned int)param->pvn.u.isname.name.n);
4197
4198
0
  return 0;
4199
0
}
4200
4201
4202
static int msg_flag_get(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
4203
0
{
4204
0
  if (param==NULL||res==NULL) {
4205
0
    LM_CRIT("BUG - bad parameters\n");
4206
0
    return -1;
4207
0
  }
4208
4209
0
  if ( isflagset( msg, (unsigned int)param->pvn.u.isname.name.n)==1 ) {
4210
0
    *res = pv_true;
4211
0
  } else {
4212
0
    *res = pv_false;
4213
0
  }
4214
0
  return 0;
4215
0
}
4216
4217
4218
/************** MSG TYPE function *****************/
4219
4220
static int msg_is_request_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
4221
0
{
4222
0
  if (param==NULL||res==NULL) {
4223
0
    LM_CRIT("BUG - bad parameters\n");
4224
0
    return -1;
4225
0
  }
4226
4227
0
  if ( msg->first_line.type==SIP_REQUEST ) {
4228
0
    *res = pv_true;
4229
0
  } else {
4230
0
    *res = pv_false;
4231
0
  }
4232
0
  return 0;
4233
0
}
4234
4235
4236
static int msg_type_get(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
4237
0
{
4238
0
  if (param==NULL||res==NULL) {
4239
0
    LM_CRIT("BUG - bad parameters\n");
4240
0
    return -1;
4241
0
  }
4242
4243
0
  if ( msg->first_line.type==SIP_REQUEST ) {
4244
0
    res->rs.s = "request";
4245
0
    res->rs.len = 7;
4246
0
  } else {
4247
0
    res->rs.s = "reply";
4248
0
    res->rs.len = 5;
4249
0
  }
4250
4251
0
  res->flags = PV_VAL_STR;
4252
4253
0
  return 0;
4254
0
}
4255
4256
4257
4258
/************** BRANCH FLAGS function *****************/
4259
4260
static int msg_branch_flag_parse_name(pv_spec_p sp, const str *in)
4261
0
{
4262
0
  unsigned int idx;
4263
0
  if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
4264
0
    return -1;
4265
4266
0
  if ( (idx=fixup_flag(FLAG_TYPE_BRANCH, in))==NAMED_FLAG_ERROR) {
4267
0
    LM_ERR("failed to fix the flag <%.*s>\n",in->len,in->s);
4268
0
    return -1;
4269
0
  }
4270
4271
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
4272
0
  sp->pvp.pvn.u.isname.type = 0;
4273
4274
0
  sp->pvp.pvn.u.isname.name.n = idx;
4275
4276
0
  return 0;
4277
0
}
4278
4279
4280
static int msg_branch_flag_set(struct sip_msg* msg, pv_param_t *param, int op,
4281
                              pv_value_t *val)
4282
0
{
4283
0
  int size;
4284
0
  int idx;
4285
0
  int idxf;
4286
4287
0
  if(param==NULL) {
4288
0
    LM_ERR("bad parameters\n");
4289
0
    return -1;
4290
0
  }
4291
4292
0
  if (val==NULL || (val->flags&(PV_VAL_NULL|PV_VAL_NONE))!=0 ||
4293
0
  (val->flags&PV_TYPE_INT)==0 ) {
4294
0
    LM_ERR("input for $branch.flag() found not to be an integer\n");
4295
0
    return -1;
4296
0
  }
4297
4298
  /* get the index */
4299
0
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
4300
0
    LM_ERR("invalid index\n");
4301
0
    return -1;
4302
0
  }
4303
4304
0
  if(idxf==PV_IDX_ALL) {
4305
0
    LM_ERR("SCRIPT BUG - * not allowed in branch flag assignment\n");
4306
0
    return -1;
4307
0
  }
4308
4309
0
  size = get_dset_size() + 1;
4310
4311
  /* if no idx, work with the last branch */
4312
0
  if (idxf==0 && idx==0)
4313
0
    idx = size - 1;
4314
4315
0
  if (idx<0) {
4316
0
    idx = size + idx;
4317
0
  }
4318
4319
0
  if (idx<0 || idx>=size) {
4320
0
    LM_DBG("inexisting branch flag assignment [%d/%d]\n", size, idx);
4321
0
    return -1;
4322
0
  }
4323
4324
0
  if (val->ri==0)
4325
0
    resetbflag (msg, idx, param->pvn.u.isname.name.n);
4326
0
  else
4327
0
    setbflag( msg, idx, param->pvn.u.isname.name.n);
4328
4329
0
  return 0;
4330
0
}
4331
4332
4333
static int msg_branch_flag_get(struct sip_msg *msg,  pv_param_t *param,
4334
                              pv_value_t *res)
4335
0
{
4336
0
  int size;
4337
0
  int idx;
4338
0
  int idxf;
4339
4340
0
  if (param==NULL||res==NULL) {
4341
0
    LM_CRIT("BUG - bad parameters\n");
4342
0
    return -1;
4343
0
  }
4344
4345
  /* get the index */
4346
0
  if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
4347
0
    LM_ERR("invalid index\n");
4348
0
    return -1;
4349
0
  }
4350
4351
0
  if(idxf==PV_IDX_ALL) {
4352
0
    LM_ERR("SCRIPT BUG - * not allowed in branch flag reading\n");
4353
0
    return -1;
4354
0
  }
4355
4356
0
  size = get_dset_size();
4357
4358
0
  if (idx<0) {
4359
0
    idx = size + idx;
4360
0
  }
4361
4362
0
  if (idx<0 || idx>=size) {
4363
0
    LM_DBG("inexisting branch flag reading [%d/%d]\n", size, idx);
4364
0
    return -1;
4365
0
  }
4366
4367
0
  if ( isbflagset( msg, idx, param->pvn.u.isname.name.n)==1 ) {
4368
0
    *res = pv_true;
4369
0
  } else {
4370
0
    *res = pv_false;
4371
0
  }
4372
0
  return 0;
4373
0
}
4374
4375
4376
/********** generic helper functions ***************/
4377
4378
/**
4379
 * the table with core pseudo-variables
4380
 */
4381
#ifndef FUZZ_BUILD
4382
static
4383
#endif
4384
const pv_export_t _pv_names_table[] = {
4385
  {str_const_init("avp"), PVT_AVP, pv_get_avp, pv_set_avp,
4386
    pv_parse_avp_name, pv_parse_avp_index, 0, 0},
4387
  {str_const_init("hdr"), PVT_HDR, pv_get_hdr, 0, pv_parse_hdr_name,
4388
    pv_parse_index, 0, 0},
4389
  {str_const_init("hdr_name"), PVT_HDR_NAME, pv_get_hdr_name, 0, 0,
4390
    pv_parse_index, 0, 0},
4391
  {str_const_init("hdrcnt"), PVT_HDRCNT, pv_get_hdrcnt, 0, pv_parse_hdr_name, 0, 0, 0},
4392
  {str_const_init("var"), PVT_SCRIPTVAR, pv_get_scriptvar,
4393
    pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0},
4394
  {str_const_init("ai"), /* */
4395
    PVT_PAI_URI, pv_get_pai, 0,
4396
    0, 0, 0, 0},
4397
  {str_const_init("au"), /* */
4398
    PVT_AUTH_USERNAME, pv_get_authattr, 0,
4399
    0, 0, pv_init_iname, 1},
4400
  {str_const_init("ar"), /* auth realm */
4401
    PVT_AUTH_REALM, pv_get_authattr, 0,
4402
    0, 0, pv_init_iname, 2},
4403
  {str_const_init("adu"), /* auth digest uri */
4404
    PVT_AUTH_DURI, pv_get_authattr, 0,
4405
    0, 0, pv_init_iname, 3},
4406
  {str_const_init("ad"), /* */
4407
    PVT_AUTH_DOMAIN, pv_get_authattr, 0,
4408
    0, 0, pv_init_iname, 4},
4409
  {str_const_init("an"), /* */
4410
    PVT_AUTH_NONCE, pv_get_authattr, 0,
4411
    0, 0, pv_init_iname, 5},
4412
  {str_const_init("auth.nonce"), /* */
4413
    PVT_AUTH_NONCE, pv_get_authattr, 0,
4414
    0, 0, pv_init_iname, 5},
4415
  {str_const_init("auth.resp"), /* */
4416
    PVT_AUTH_RESPONSE, pv_get_authattr, 0,
4417
    0, 0, pv_init_iname, 6},
4418
  {str_const_init("auth.cnonce"), /* */
4419
    PVT_AUTH_CNONCE, pv_get_authattr, 0,
4420
    0, 0, pv_init_iname, 7},
4421
  {str_const_init("auth.opaque"), /* */
4422
    PVT_AUTH_OPAQUE, pv_get_authattr, 0,
4423
    0, 0, pv_init_iname, 8},
4424
  {str_const_init("auth.alg"), /* */
4425
    PVT_AUTH_ALGORITHM, pv_get_authattr, 0,
4426
    0, 0, pv_init_iname, 9},
4427
  {str_const_init("auth.qop"), /* */
4428
    PVT_AUTH_QOP, pv_get_authattr, 0,
4429
    0, 0, pv_init_iname, 10},
4430
  {str_const_init("auth.nc"), /* */
4431
    PVT_AUTH_NONCE_COUNT, pv_get_authattr, 0,
4432
    0, 0, pv_init_iname, 11},
4433
  {str_const_init("aU"), /* */
4434
    PVT_AUTH_USERNAME_WHOLE, pv_get_authattr, 0,
4435
    0, 0, pv_init_iname, 99},
4436
  {str_const_init("challenge.algorithm"), /* */
4437
    PVT_AUTH_USERNAME, pv_get_cauthattr, 0,
4438
    0, 0, pv_init_iname, 1},
4439
  {str_const_init("challenge.realm"),
4440
    PVT_AUTH_REALM, pv_get_cauthattr, 0,
4441
    0, 0, pv_init_iname, 2},
4442
  {str_const_init("challenge.nonce"),
4443
    PVT_AUTH_DURI, pv_get_cauthattr, 0,
4444
    0, 0, pv_init_iname, 3},
4445
  {str_const_init("challenge.opaque"),
4446
    PVT_AUTH_DOMAIN, pv_get_cauthattr, 0,
4447
    0, 0, pv_init_iname, 4},
4448
  {str_const_init("challenge.qop"),
4449
    PVT_AUTH_NONCE, pv_get_cauthattr, 0,
4450
    0, 0, pv_init_iname, 5},
4451
  {str_const_init("challenge.ik"), /* */
4452
    PVT_AUTH_NONCE, pv_get_cauthattr, 0,
4453
    0, 0, pv_init_iname, 6},
4454
  {str_const_init("challenge.ck"), /* */
4455
    PVT_AUTH_RESPONSE, pv_get_cauthattr, 0,
4456
    0, 0, pv_init_iname, 7},
4457
  {str_const_init("Au"), /* */
4458
    PVT_ACC_USERNAME, pv_get_acc_username, 0,
4459
    0, 0, pv_init_iname, 1},
4460
  {str_const_init("bf"), /* */
4461
    PVT_BFLAGS, pv_get_bflags, 0,
4462
    0, 0, 0, 0},
4463
  {str_const_init("branch"), /* to be obsolete */
4464
    PVT_BRANCH, pv_get_branch_fields, pv_set_msg_branch,
4465
    0, 0, 0, 0},
4466
  {str_const_init("branch"), /* to be obsolete */
4467
    PVT_BRANCH, pv_get_branch_fields, pv_set_branch_fields,
4468
    pv_parse_branch_name, pv_parse_index, 0, 0},
4469
  {str_const_init("branch.flag"), /* to be obsolete  */
4470
    PVT_BRANCH_FLAG, msg_branch_flag_get, msg_branch_flag_set,
4471
    msg_branch_flag_parse_name, pv_parse_index, 0, 0},
4472
  {str_const_init("ci"), /* */
4473
    PVT_CALLID, pv_get_callid, 0,
4474
    0, 0, 0, 0},
4475
  {str_const_init("cl"), /* */
4476
    PVT_CONTENT_LENGTH, pv_get_content_length, 0,
4477
    0, 0, 0, 0},
4478
  {str_const_init("cs"), /* */
4479
    PVT_CSEQ, pv_get_cseq, 0,
4480
    0, 0, 0, 0},
4481
  {str_const_init("ct"), /* */
4482
    PVT_CONTACT, pv_get_contact_body, 0,
4483
    0, pv_parse_index, 0, 0},
4484
  {str_const_init("ct.fields"), /* */
4485
    PVT_CONTACT, pv_get_contact_body, 0,
4486
    pv_parse_ct_name, pv_parse_index, 0, 0},
4487
  {str_const_init("cT"), /* */
4488
    PVT_CONTENT_TYPE, pv_get_content_type, 0,
4489
    0, pv_parse_index, 0, 0},
4490
  {str_const_init("dd"), /* */
4491
    PVT_DSTURI_DOMAIN, pv_get_dsturi_attr, pv_set_dsturi_host,
4492
    0, 0, pv_init_iname, 1},
4493
  {str_const_init("di"), /* */
4494
    PVT_DIVERSION_URI, pv_get_diversion, 0,
4495
    0, 0, pv_init_iname, 1},
4496
  {str_const_init("dir"), /* */
4497
    PVT_DIV_REASON, pv_get_diversion, 0,
4498
    0, 0, pv_init_iname, 2},
4499
  {str_const_init("dip"), /* */
4500
    PVT_DIV_PRIVACY, pv_get_diversion, 0,
4501
    0, 0, pv_init_iname, 3},
4502
  {str_const_init("dp"), /* */
4503
    PVT_DSTURI_PORT, pv_get_dsturi_attr, pv_set_dsturi_port,
4504
    0, 0, pv_init_iname, 2},
4505
  {str_const_init("dP"), /* */
4506
    PVT_DSTURI_PROTOCOL, pv_get_dsturi_attr, 0,
4507
    0, 0, pv_init_iname, 3},
4508
  {str_const_init("ds"), /* */
4509
    PVT_DSET, pv_get_dset, 0,
4510
    0, 0, 0, 0},
4511
  {str_const_init("du"), /* */
4512
    PVT_DSTURI, pv_get_dsturi, pv_set_dsturi,
4513
    0, 0, 0, 0},
4514
  {str_const_init("duri"), /* */
4515
    PVT_DSTURI, pv_get_dsturi, pv_set_dsturi,
4516
    0, 0, 0, 0},
4517
  {str_const_init("err.class"), /* */
4518
    PVT_ERR_CLASS, pv_get_errinfo_attr, 0,
4519
    0, 0, 0, 0},
4520
  {str_const_init("err.level"), /* */
4521
    PVT_ERR_LEVEL, pv_get_errinfo_attr, 0,
4522
    0, 0, pv_init_iname, 1},
4523
  {str_const_init("err.info"), /* */
4524
    PVT_ERR_INFO, pv_get_errinfo_attr, 0,
4525
    0, 0, pv_init_iname, 2},
4526
  {str_const_init("err.rcode"), /* */
4527
    PVT_ERR_RCODE, pv_get_errinfo_attr, 0,
4528
    0, 0, pv_init_iname, 3},
4529
  {str_const_init("err.rreason"), /* */
4530
    PVT_ERR_RREASON, pv_get_errinfo_attr, 0,
4531
    0, 0, pv_init_iname, 4},
4532
  {str_const_init("fd"), /* */
4533
    PVT_FROM_DOMAIN, pv_get_from_attr, 0,
4534
    0, 0, pv_init_iname, 3},
4535
  {str_const_init("from.domain"), /* */
4536
    PVT_FROM_DOMAIN, pv_get_from_attr, 0,
4537
    0, 0, pv_init_iname, 3},
4538
  {str_const_init("fn"), /* */
4539
    PVT_FROM_DISPLAYNAME, pv_get_from_attr, 0,
4540
    0, 0, pv_init_iname, 5},
4541
  {str_const_init("ft"), /* */
4542
    PVT_FROM_TAG, pv_get_from_attr, 0,
4543
    0, 0, pv_init_iname, 4},
4544
  {str_const_init("fu"), /* */
4545
    PVT_FROM, pv_get_from_attr, 0,
4546
    0, 0, pv_init_iname, 1},
4547
  {str_const_init("from"), /* */
4548
    PVT_FROM, pv_get_from_attr, 0,
4549
    0, 0, pv_init_iname, 1},
4550
  {str_const_init("fU"), /* */
4551
    PVT_FROM_USERNAME, pv_get_from_attr, 0,
4552
    0, 0, pv_init_iname, 2},
4553
  {str_const_init("from.user"), /* */
4554
    PVT_FROM_USERNAME, pv_get_from_attr, 0,
4555
    0, 0, pv_init_iname, 2},
4556
  {str_const_init("log_level"), /* per process log level*/
4557
    PVT_LOG_LEVEL, pv_get_log_level, pv_set_log_level,
4558
    0, 0, 0, 0},
4559
  {str_const_init("mb"), /* */
4560
    PVT_MSG_BUF, pv_get_msg_buf, 0,
4561
    0, 0, 0, 0},
4562
  {str_const_init("mf"), /* */
4563
    PVT_FLAGS, pv_get_flags, 0,
4564
    0, 0, 0, 0},
4565
  {str_const_init("msg.flag"), /* */
4566
    PVT_MSG_FLAG, msg_flag_get, msg_flag_set,
4567
    msg_flag_parse_name, 0, 0, 0},
4568
  {str_const_init("msg.is_request"), /* */
4569
    PVT_MSG_FLAG, msg_is_request_get, 0,
4570
    0, 0, 0, 0},
4571
  {str_const_init("msg.type"), /* */
4572
    PVT_MSG_FLAG, msg_type_get, 0,
4573
    0, 0, 0, 0},
4574
4575
  {str_const_init("msg.branch"), /* */
4576
    PVT_BRANCH, pv_get_branch_fields, pv_set_msg_branch,
4577
    0, 0, 0, 0},
4578
  {str_const_init("msg.branch.uri"), /* */
4579
    PVT_BRANCH, pv_get_msg_branch_uri, pv_set_msg_branch_uri,
4580
    0, pv_parse_index, 0, 0},
4581
  {str_const_init("msg.branch.duri"), /* */
4582
    PVT_BRANCH, pv_get_msg_branch_duri, pv_set_msg_branch_duri,
4583
    0, pv_parse_index, 0, 0},
4584
  {str_const_init("msg.branch.path"), /* */
4585
    PVT_BRANCH, pv_get_msg_branch_path, pv_set_msg_branch_path,
4586
    0, pv_parse_index, 0, 0},
4587
  {str_const_init("msg.branch.q"), /* */
4588
    PVT_BRANCH, pv_get_msg_branch_q, pv_set_msg_branch_q,
4589
    0, pv_parse_index, 0, 0},
4590
  {str_const_init("msg.branch.flags"), /* */
4591
    PVT_BRANCH, pv_get_msg_branch_flags, pv_set_msg_branch_flags,
4592
    0, pv_parse_index, 0, 0},
4593
  {str_const_init("msg.branch.socket"), /* */
4594
    PVT_BRANCH, pv_get_msg_branch_sock, pv_set_msg_branch_sock,
4595
    0, pv_parse_index, 0, 0},
4596
  {str_const_init("msg.branch.flag"), /* */
4597
    PVT_BRANCH_FLAG, msg_branch_flag_get, msg_branch_flag_set,
4598
    msg_branch_flag_parse_name, pv_parse_index, 0, 0},
4599
  {str_const_init("msg.branch.attr"), /* */
4600
    PVT_BRANCH, pv_get_msg_branch_attr, pv_set_msg_branch_attr,
4601
    pv_parse_avp_name, pv_parse_index, 0, 0},
4602
  {str_const_init("msg.branch.last_idx"), /* */
4603
    PVT_BRANCH, pv_get_msg_branch_lastidx, NULL,
4604
    NULL, NULL, 0, 0},
4605
  {str_const_init("mi"), /* */
4606
    PVT_MSGID, pv_get_msgid, 0,
4607
    0, 0, 0, 0},
4608
  {str_const_init("ml"), /* */
4609
    PVT_MSG_LEN, pv_get_msg_len, 0,
4610
    0, 0, 0, 0},
4611
  {str_const_init("od"), /* */
4612
    PVT_OURI_DOMAIN, pv_get_ouri_attr, 0,
4613
    0, 0, pv_init_iname, 2},
4614
  {str_const_init("op"), /* */
4615
    PVT_OURI_PORT, pv_get_ouri_attr, 0,
4616
    0, 0, pv_init_iname, 3},
4617
  {str_const_init("oP"), /* */
4618
    PVT_OURI_PROTOCOL, pv_get_ouri_attr, 0,
4619
    0, 0, pv_init_iname, 4},
4620
  {str_const_init("ou"), /* */
4621
    PVT_OURI, pv_get_ouri, 0,
4622
    0, 0, 0, 0},
4623
  {str_const_init("ouri"), /* */
4624
    PVT_OURI, pv_get_ouri, 0,
4625
    0, 0, 0, 0},
4626
  {str_const_init("oU"), /* */
4627
    PVT_OURI_USERNAME, pv_get_ouri_attr, 0,
4628
    0, 0, pv_init_iname, 1},
4629
  {str_const_init("path"), /* */
4630
    PVT_PATH, pv_get_path, 0,
4631
    0, 0, 0, 0},
4632
  {str_const_init("pd"), /* */
4633
    PVT_PPI_DOMAIN, pv_get_ppi_attr, 0,
4634
    0, 0, pv_init_iname, 3},
4635
  {str_const_init("pn"), /* */
4636
    PVT_PPI_DISPLAYNAME, pv_get_ppi_attr, 0,
4637
    0, 0, pv_init_iname, 4},
4638
  {str_const_init("pp"), /* */
4639
    PVT_PID, pv_get_pid, 0,
4640
    0, 0, 0, 0},
4641
  {str_const_init("pu"), /* */
4642
    PVT_PPI, pv_get_ppi_attr, 0,
4643
    0, 0, pv_init_iname, 1},
4644
  {str_const_init("pU"), /* */
4645
    PVT_PPI_USERNAME, pv_get_ppi_attr, 0,
4646
    0, 0, pv_init_iname, 2},
4647
  {str_const_init("rb"), /* */
4648
    PVT_MSG_BODY, pv_get_msg_body, 0,
4649
    0, pv_parse_index, 0, 0},
4650
  {str_const_init("rb"), /* */
4651
    PVT_MSG_BODY, pv_get_msg_body, 0,
4652
    pv_parse_rb_name, pv_parse_index, 0, 0},
4653
  {str_const_init("rc"), /* */
4654
    PVT_RETURN_CODE, pv_get_return_code, 0,
4655
    0, 0, 0, 0},
4656
  {str_const_init("retcode"), /* */
4657
    PVT_RETURN_CODE, pv_get_return_code, 0,
4658
    0, 0, 0, 0},
4659
  {str_const_init("rd"), /* */
4660
    PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host,
4661
    0, 0, pv_init_iname, 2},
4662
  {str_const_init("ruri.domain"), /* */
4663
    PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host,
4664
    0, 0, pv_init_iname, 2},
4665
  {str_const_init("re"), /* */
4666
    PVT_RPID_URI, pv_get_rpid, 0,
4667
    0, 0, 0, 0},
4668
  {str_const_init("rm"), /* */
4669
    PVT_METHOD, pv_get_method, 0,
4670
    0, 0, 0, 0},
4671
  {str_const_init("route"), /* */
4672
    PVT_ROUTE, pv_get_route, 0,
4673
    0, pv_parse_index, 0, 0},
4674
  {str_const_init("route.name"), /* */
4675
    PVT_ROUTE_NAME, pv_get_route_name, 0,
4676
    0, pv_parse_index, 0, 0},
4677
  {str_const_init("route.type"), /* */
4678
    PVT_ROUTE_TYPE, pv_get_route_type, 0,
4679
    0, pv_parse_index, 0, 0},
4680
  {str_const_init("rp"), /* */
4681
    PVT_RURI_PORT, pv_get_ruri_attr, pv_set_ruri_port,
4682
    0, 0, pv_init_iname, 3},
4683
  {str_const_init("rP"), /* */
4684
    PVT_RURI_PROTOCOL, pv_get_ruri_attr, 0,
4685
    0, 0, pv_init_iname, 4},
4686
  {str_const_init("rr"), /* */
4687
    PVT_REASON, pv_get_reason, 0,
4688
    0, 0, 0, 0},
4689
  {str_const_init("rs"), /* */
4690
    PVT_STATUS, pv_get_status, 0,
4691
    0, 0, 0, 0},
4692
  {str_const_init("rt"), /* */
4693
    PVT_REFER_TO, pv_get_refer_to, 0,
4694
    0, 0, 0, 0},
4695
  {str_const_init("ru"), /* */
4696
    PVT_RURI, pv_get_ruri, pv_set_ruri,
4697
    0, 0, 0, 0},
4698
  {str_const_init("ruri"), /* */
4699
    PVT_RURI, pv_get_ruri, pv_set_ruri,
4700
    0, 0, 0, 0},
4701
  {str_const_init("ru_q"), /* */
4702
    PVT_RU_Q, pv_get_ru_q, pv_set_ru_q,
4703
    0, 0, 0, 0},
4704
  {str_const_init("rU"), /* */
4705
    PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user,
4706
    0, 0, pv_init_iname, 1},
4707
  {str_const_init("ruri.user"), /* */
4708
    PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user,
4709
    0, 0, pv_init_iname, 1},
4710
  {str_const_init("sdp"), /* */
4711
    PVT_SDP, pv_get_sdp, pv_set_sdp,
4712
    0, 0, pv_init_iname, 1},
4713
  {str_const_init("sdp"), /* */
4714
    PVT_SDP, pv_get_sdp, pv_set_sdp,
4715
    pv_parse_sdp_name, 0, pv_init_iname, 1},
4716
  {str_const_init("sdp.line"), /* */
4717
    PVT_SDP_LINE, pv_get_sdp_line, pv_set_sdp_line,
4718
    pv_parse_sdp_line_name, pv_parse_sdp_line_index, 0, 0},
4719
  {str_const_init("sdp.stream"), /* */
4720
    PVT_SDP_STREAM, pv_get_sdp_stream, pv_set_sdp_stream,
4721
    pv_parse_sdp_stream_name, pv_parse_sdp_line_index, 0, 0},
4722
  {str_const_init("sdp.stream.idx"), /* */
4723
    PVT_SDP_LINE, pv_get_sdp_stream_idx, 0,
4724
    pv_parse_sdp_stream_name, 0, 0, 0},
4725
  {str_const_init("sdp.session"), /* */
4726
    PVT_SDP_SESSION, pv_get_sdp_session, pv_set_sdp_session,
4727
    pv_parse_sdp_line_name, pv_parse_sdp_line_index, 0, 0},
4728
  {str_const_init("src_ip"), /* */
4729
    PVT_SRCIP, pv_get_srcip, 0,
4730
    0, 0, 0, 0},
4731
  {str_const_init("socket_in"), /* */
4732
    PVT_SOCKET_IN, pv_get_socket_in_fields, NULL,
4733
    0, 0, 0, 0},
4734
  {str_const_init("socket_in"), /* */
4735
    PVT_SOCKET_IN, pv_get_socket_in_fields, NULL,
4736
    pv_parse_socket_name, 0, 0, 0},
4737
  {str_const_init("socket_out"), /* */
4738
    PVT_SOCKET_OUT, pv_get_socket_out_fields, pv_set_force_sock,
4739
    0, 0, 0, 0},
4740
  {str_const_init("socket_out"), /* */
4741
    PVT_SOCKET_OUT, pv_get_socket_out_fields, NULL,
4742
    pv_parse_socket_out_name, 0, 0, 0},
4743
  {str_const_init("si"), /* */
4744
    PVT_SRCIP, pv_get_srcip, 0,
4745
    0, 0, 0, 0},
4746
  {str_const_init("sp"), /* */
4747
    PVT_SRCPORT, pv_get_srcport, 0,
4748
    0, 0, 0, 0},
4749
  {str_const_init("td"), /* */
4750
    PVT_TO_DOMAIN, pv_get_to_attr, 0,
4751
    0, 0, pv_init_iname, 3},
4752
  {str_const_init("to.domain"), /* */
4753
    PVT_TO_DOMAIN, pv_get_to_attr, 0,
4754
    0, 0, pv_init_iname, 3},
4755
  {str_const_init("time"), /* */
4756
    PVT_TIME, pv_get_formated_time, 0,
4757
    pv_parse_time_name, 0, 0, 0},
4758
  {str_const_init("tn"), /* */
4759
    PVT_TO_DISPLAYNAME, pv_get_to_attr, 0,
4760
    0, 0, pv_init_iname, 5},
4761
  {str_const_init("tt"), /* */
4762
    PVT_TO_TAG, pv_get_to_attr, 0,
4763
    0, 0, pv_init_iname, 4},
4764
  {str_const_init("tu"), /* */
4765
    PVT_TO, pv_get_to_attr, 0,
4766
    0, 0, pv_init_iname, 1},
4767
  {str_const_init("to"), /* */
4768
    PVT_TO, pv_get_to_attr, 0,
4769
    0, 0, pv_init_iname, 1},
4770
  {str_const_init("tU"), /* */
4771
    PVT_TO_USERNAME, pv_get_to_attr, 0,
4772
    0, 0, pv_init_iname, 2},
4773
  {str_const_init("to.user"), /* */
4774
    PVT_TO_USERNAME, pv_get_to_attr, 0,
4775
    0, 0, pv_init_iname, 2},
4776
  {str_const_init("Tf"), /* */
4777
    PVT_TIMEF, pv_get_timef, 0,
4778
    0, 0, 0, 0},
4779
  {str_const_init("Ts"), /* */
4780
    PVT_TIMES, pv_get_times, 0,
4781
    0, 0, 0, 0},
4782
  {str_const_init("Tsm"), /* */
4783
    PVT_TIMES, pv_get_timem, 0,
4784
    0, 0, 0, 0},
4785
  {str_const_init("TS"), /* */
4786
    PVT_TIMES, pv_get_start_times, 0,
4787
    0, 0, 0, 0},
4788
  {str_const_init("ua"), /* */
4789
    PVT_USERAGENT, pv_get_useragent, 0,
4790
    0, 0, 0, 0},
4791
  {str_const_init("C"), PVT_COLOR, pv_get_color, 0,
4792
    pv_parse_color_name, 0, 0, 0 },
4793
  {str_const_init("argv"), PVT_ARGV, pv_get_argv, 0,
4794
    pv_parse_argv_name, 0, 0, 0 },
4795
  {str_const_init("param"), PVT_ROUTE_PARAM, pv_get_param, 0,
4796
    pv_parse_param_name, 0, 0, 0 },
4797
  {str_const_init("cfg_line"), PVT_LINE_NUMBER, pv_get_line_number, 0,
4798
    0, 0, 0, 0 },
4799
  {str_const_init("cfg_file"), PVT_CFG_FILE_NAME, pv_get_cfg_file_name, 0,
4800
  0, 0, 0, 0 },
4801
  {str_const_init("xlog_level"), PVT_XLOG_LEVEL, pv_get_xlog_level,
4802
    pv_set_xlog_level, 0, 0, 0, 0 },
4803
  {str_const_init("return"), PVT_EXTRA, pv_get_return_value, 0,
4804
    pv_parse_return_value, 0, 0, 0 },
4805
  {{0,0}, 0, 0, 0, 0, 0, 0, 0}
4806
};
4807
4808
static const pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e, int has_name)
4809
0
{
4810
0
  int i;
4811
0
  pv_extra_p pvi;
4812
0
  int found;
4813
4814
0
  if(pvname==0 || e==0)
4815
0
  {
4816
0
    LM_ERR("bad parameters\n");
4817
0
    return NULL;
4818
0
  }
4819
  /* search in main table */
4820
0
  for(i=0; _pv_names_table[i].name.s!=0; i++)
4821
0
  {
4822
0
    if(_pv_names_table[i].name.len==pvname->len
4823
0
      && !((has_name?1:0) ^ (_pv_names_table[i].parse_name?1:0))
4824
0
      && memcmp(_pv_names_table[i].name.s, pvname->s, pvname->len)==0)
4825
0
    {
4826
      /*LM_DBG("found [%.*s] [%d]\n", pvname->len, pvname->s,
4827
          _pv_names_table[i].type);*/
4828
      /* copy data from table to spec */
4829
0
      e->type = _pv_names_table[i].type;
4830
0
      e->getf = _pv_names_table[i].getf;
4831
0
      e->setf = _pv_names_table[i].setf;
4832
0
      return &_pv_names_table[i];
4833
0
    }
4834
0
  }
4835
  /* search in extra list */
4836
0
  if(_pv_extra_list==0)
4837
0
  {
4838
0
    LM_DBG("extra items list is empty\n");
4839
0
    return NULL;
4840
0
  }
4841
0
  pvi = *_pv_extra_list;
4842
0
  while(pvi)
4843
0
  {
4844
0
    if(pvi->pve.name.len>pvname->len)
4845
0
      break;
4846
0
    if(pvi->pve.name.len==pvname->len)
4847
0
    {
4848
0
      found = strncmp(pvi->pve.name.s, pvname->s, pvname->len);
4849
0
      if(found>0)
4850
0
        break;
4851
0
      if(found==0)
4852
0
      {
4853
0
        LM_DBG("found in extra list [%.*s]\n", pvname->len, pvname->s);
4854
        /* copy data from export to spec */
4855
0
        e->type = pvi->pve.type;
4856
0
        e->getf = pvi->pve.getf;
4857
0
        e->setf = pvi->pve.setf;
4858
0
        return &(pvi->pve);
4859
0
      }
4860
0
    }
4861
0
    pvi = pvi->next;
4862
0
  }
4863
4864
0
  return NULL;
4865
0
}
4866
4867
static int is_pv_valid_char(char c)
4868
0
{
4869
0
  if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')
4870
0
      || (c=='_') || (c=='.'))
4871
0
    return 1;
4872
0
  return 0;
4873
0
}
4874
4875
char* pv_parse_spec(const str *in, const pv_spec_p e)
4876
0
{
4877
0
  char *p;
4878
0
  str s;
4879
0
  str pvname;
4880
0
  str pvcontext;
4881
0
  int pvstate;
4882
0
  int has_inner_name;
4883
0
  trans_t *tr = NULL;
4884
0
  const pv_export_t *pte = NULL;
4885
0
  int n=0;
4886
4887
0
  if(in==NULL || in->s==NULL || e==NULL || *in->s!=PV_MARKER)
4888
0
  {
4889
0
    LM_ERR("bad parameters\n");
4890
0
    return NULL;
4891
0
  }
4892
4893
//  LM_DBG("***** input [%.*s] (%d)\n", in->len, in->s, in->len);
4894
0
  tr = 0;
4895
0
  pvstate = 0;
4896
0
  memset(e, 0, sizeof(pv_spec_t));
4897
0
  p = in->s;
4898
0
  p++;
4899
0
  if(*p==PV_LNBRACKET)
4900
0
  {
4901
0
    p++;
4902
0
    pvstate = 1;
4903
0
  }
4904
0
  pvname.s = p;
4905
0
  if(*p == PV_MARKER) {
4906
0
    p++;
4907
0
    if(pvstate==1)
4908
0
    {
4909
0
      if(*p!=PV_RNBRACKET)
4910
0
        goto error;
4911
0
      p++;
4912
0
    }
4913
0
    e->getf = pv_get_marker;
4914
0
    e->type = PVT_MARKER;
4915
0
    pvname.len = 1;
4916
0
    goto done_all;
4917
0
  }
4918
4919
0
  if (*p==PV_LCBRACKET)
4920
0
  { /* context definition*/
4921
0
    p++;
4922
0
    pvcontext.s = p;
4923
4924
0
    while(is_in_str(p,in) && is_pv_valid_char(*p))
4925
0
      p++;
4926
4927
0
    if(*p != PV_RCBRACKET)
4928
0
    {
4929
0
      LM_ERR("Expected to find the end of the context\n");
4930
0
      return 0;
4931
0
    }
4932
0
    pvcontext.len = p - pvcontext.s;
4933
0
    LM_DBG("Context name is %.*s\n", pvcontext.len, pvcontext.s);
4934
0
    p++;
4935
0
    e->pvc = pv_get_context(&pvcontext);
4936
0
    if(e->pvc == NULL)
4937
0
    {
4938
0
      if(!pvc_before_check)
4939
0
      {
4940
0
        LM_ERR("Requested a non existing pv context\n");
4941
0
        return 0;
4942
0
      }
4943
0
      LM_DBG("No context definition found for [%.*s]\n", pvcontext.len, pvcontext.s);
4944
      /* create a dummy context strcuture to be filled by the register functions */
4945
0
      e->pvc = add_pv_context(&pvcontext, 0);
4946
0
      if(e->pvc == NULL )
4947
0
      {
4948
0
        LM_ERR("Failed to new context\n");
4949
0
        return 0;
4950
0
      }
4951
0
    }
4952
0
  }
4953
4954
0
  pvname.s = p;
4955
0
  while(is_in_str(p,in) && is_pv_valid_char(*p))
4956
0
    p++;
4957
0
  pvname.len = p - pvname.s;
4958
4959
0
  if(pvstate==1)
4960
0
  {
4961
0
    if(*p==PV_RNBRACKET)
4962
0
    { /* full pv name ended here*/
4963
0
      goto done_inm;
4964
0
    } else if(*p==PV_LNBRACKET) {
4965
0
      p++;
4966
0
      pvstate = 2;
4967
0
    } else if(*p==PV_LIBRACKET) {
4968
0
      p++;
4969
0
      pvstate = 3;
4970
0
    } else if(*p==TR_LBRACKET) {
4971
0
      p++;
4972
0
      pvstate = 4;
4973
0
    }
4974
0
    else {
4975
0
      LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
4976
0
          pvstate);
4977
0
      goto error;
4978
0
    }
4979
0
  } else {
4980
0
    if(!is_in_str(p, in)) {
4981
0
      p--;
4982
0
      goto done_inm;
4983
0
    } else if(*p==PV_LNBRACKET) {
4984
0
      p++;
4985
0
      pvstate = 5;
4986
0
    } else {
4987
      /* still in input str, but end of PV */
4988
      /* p is increased at the end, so decrement here */
4989
0
      p--;
4990
0
      goto done_inm;
4991
0
    }
4992
0
  }
4993
4994
0
done_inm:
4995
0
  has_inner_name = (pvstate==2||pvstate==5)?1:0;
4996
0
  if((pte = pv_lookup_spec_name(&pvname, e, has_inner_name))==NULL)
4997
0
  {
4998
0
    LM_ERR("unknown script var $%.*s%s, maybe a 'loadmodule' statement "
4999
0
           "is missing?\n", pvname.len, pvname.s,has_inner_name ? "()":"");
5000
0
    goto error;
5001
0
  }
5002
0
  if(pvstate==2 || pvstate==5)
5003
0
  {
5004
0
    s.s = p;
5005
0
    n = 0;
5006
0
    while(is_in_str(p, in))
5007
0
    {
5008
0
      if(*p==PV_RNBRACKET)
5009
0
      {
5010
0
        if(n==0)
5011
0
          break;
5012
0
        n--;
5013
0
      }
5014
0
      if(*p == PV_LNBRACKET)
5015
0
        n++;
5016
0
      p++;
5017
0
    }
5018
5019
0
    if(!is_in_str(p, in))
5020
0
      goto error;
5021
5022
0
    if(p==s.s)
5023
0
    {
5024
0
      LM_ERR("pvar \"%.*s\" does not get empty name param\n",
5025
0
          pvname.len, pvname.s);
5026
0
      goto error;
5027
0
    }
5028
0
    s.len = p - s.s;
5029
0
    if(pte->parse_name == NULL || pte->parse_name(e, &s)!=0)
5030
0
    {
5031
0
      LM_ERR("pvar \"%.*s\" has an invalid name param [%.*s]\n",
5032
0
          pvname.len, pvname.s, s.len, s.s);
5033
0
      goto error;
5034
0
    }
5035
0
    if(pvstate==2)
5036
0
    {
5037
0
      p++;
5038
0
      if(*p==PV_RNBRACKET)
5039
0
      { /* full pv name ended here*/
5040
0
        goto done_vnm;
5041
0
      } else if(*p==PV_LIBRACKET) {
5042
0
        p++;
5043
0
        pvstate = 3;
5044
0
      } else if(*p==TR_LBRACKET) {
5045
0
        p++;
5046
0
        pvstate = 4;
5047
0
      } else {
5048
0
        LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
5049
0
          pvstate);
5050
0
        goto error;
5051
0
      }
5052
0
    } else {
5053
0
      if(*p==PV_RNBRACKET)
5054
0
      { /* full pv name ended here*/
5055
0
        p++;
5056
0
        goto done_all;
5057
0
      } else {
5058
0
        LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
5059
0
          pvstate);
5060
0
        goto error;
5061
0
      }
5062
0
    }
5063
0
  }
5064
0
done_vnm:
5065
0
  if(pvstate==3)
5066
0
  {
5067
0
    if(pte->parse_index==NULL)
5068
0
    {
5069
0
      LM_ERR("pvar \"%.*s\" does not get index param\n",
5070
0
          pvname.len, pvname.s);
5071
0
      goto error;
5072
0
    }
5073
0
    s.s = p;
5074
0
    n = 0;
5075
0
    while(is_in_str(p, in))
5076
0
    {
5077
0
      if(*p==PV_RIBRACKET)
5078
0
      {
5079
0
        if(n==0)
5080
0
          break;
5081
0
        n--;
5082
0
      }
5083
0
      if(*p == PV_LIBRACKET)
5084
0
        n++;
5085
0
      p++;
5086
0
    }
5087
0
    if(!is_in_str(p, in))
5088
0
      goto error;
5089
5090
0
    if(p==s.s)
5091
0
    {
5092
0
      LM_ERR("pvar \"%.*s\" does not get empty index param\n",
5093
0
          pvname.len, pvname.s);
5094
0
      goto error;
5095
0
    }
5096
0
    s.len = p - s.s;
5097
0
    if(pte->parse_index(e, &s)!=0)
5098
0
    {
5099
0
      LM_ERR("pvar \"%.*s\" has an invalid index param [%.*s]\n",
5100
0
          pvname.len, pvname.s, s.len, s.s);
5101
0
      goto error;
5102
0
    }
5103
0
    p++;
5104
0
    if(*p==PV_RNBRACKET)
5105
0
    { /* full pv name ended here*/
5106
0
      goto done_idx;
5107
0
    } else if(*p==TR_LBRACKET) {
5108
0
      p++;
5109
0
      pvstate = 4;
5110
0
    } else {
5111
0
      LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
5112
0
          pvstate);
5113
0
      goto error;
5114
0
    }
5115
0
  }
5116
0
done_idx:
5117
0
  if(pvstate==4)
5118
0
  {
5119
0
    s.s = p-1;
5120
0
    n = 0;
5121
0
    while(is_in_str(p, in))
5122
0
    {
5123
0
      if(*p==TR_RBRACKET)
5124
0
      {
5125
0
        if(n==0)
5126
0
        {
5127
          /* yet another transformation */
5128
0
          p++;
5129
0
          while(is_in_str(p, in) && (*p==' ' || *p=='\t')) p++;
5130
5131
0
          if(!is_in_str(p, in) || *p != TR_LBRACKET)
5132
0
          {
5133
0
            p--;
5134
0
            break;
5135
0
          }
5136
0
        }
5137
0
        n--;
5138
0
      }
5139
0
      if(*p == TR_LBRACKET)
5140
0
        n++;
5141
0
      p++;
5142
0
    }
5143
0
    if(!is_in_str(p, in))
5144
0
      goto error;
5145
5146
0
    if(p==s.s)
5147
0
    {
5148
0
      LM_ERR("pvar \"%.*s\" does not get empty index param\n",
5149
0
          pvname.len, pvname.s);
5150
0
      goto error;
5151
0
    }
5152
0
    s.len = p - s.s + 1;
5153
5154
0
    p = parse_transformation(&s, &tr);
5155
0
    if(p==NULL)
5156
0
    {
5157
0
      LM_ERR("ERROR:bad tr in pvar name \"%.*s\"\n",
5158
0
          pvname.len, pvname.s);
5159
0
      goto error;
5160
0
    }
5161
0
    if(*p!=PV_RNBRACKET)
5162
0
    {
5163
0
      LM_ERR("bad pvar name \"%.*s\" (%c)!\n", in->len, in->s, *p);
5164
0
      goto error;
5165
0
    }
5166
0
    e->trans = (void*)tr;
5167
0
  }
5168
0
  p++;
5169
5170
0
done_all:
5171
0
  if(pte!=NULL && pte->init_param)
5172
0
    pte->init_param(e, pte->iparam);
5173
0
  return p;
5174
5175
0
error:
5176
0
  if(p!=NULL)
5177
0
    LM_ERR("wrong char [%c/%d] in [%.*s] at [%d (%d)]\n", *p, (int)*p,
5178
0
      in->len, in->s, (int)(p-in->s), pvstate);
5179
0
  else
5180
0
    LM_ERR("invalid parsing in [%.*s] at (%d)\n", in->len, in->s, pvstate);
5181
0
  return NULL;
5182
5183
0
} /* end: pv_parse_spec */
5184
5185
/**
5186
 *
5187
 */
5188
int pv_parse_format(const str *in, pv_elem_p *el)
5189
0
{
5190
0
  char *p, *p0;
5191
  /*int n = 0;*/
5192
0
  pv_elem_p e, e0;
5193
0
  str s;
5194
5195
0
  if(in==NULL || in->s==NULL || el==NULL)
5196
0
    return -1;
5197
5198
  /*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
5199
5200
0
  if(in->len == 0)
5201
0
  {
5202
0
    *el = pkg_malloc(sizeof(pv_elem_t));
5203
0
    if(*el == NULL) {
5204
0
      LM_ERR("not enough pkg memory for PV element (1)\n");
5205
0
      goto error;
5206
0
    }
5207
0
    memset(*el, 0, sizeof(pv_elem_t));
5208
0
    (*el)->text = *in;
5209
0
    return 0;
5210
0
  }
5211
5212
0
  p = in->s;
5213
0
  *el = NULL;
5214
0
  e = e0 = NULL;
5215
5216
0
  while(is_in_str(p,in))
5217
0
  {
5218
0
    e0 = e;
5219
0
    e = pkg_malloc(sizeof(pv_elem_t));
5220
0
    if(!e) {
5221
0
      LM_ERR("not enough pkg memory for PV element (2)\n");
5222
0
      goto error;
5223
0
    }
5224
0
    memset(e, 0, sizeof(pv_elem_t));
5225
    /*n++;*/
5226
0
    if(*el == NULL)
5227
0
      *el = e;
5228
0
    if(e0)
5229
0
      e0->next = e;
5230
5231
0
    e->text.s = p;
5232
0
    while(is_in_str(p,in) && *p!=PV_MARKER)
5233
0
      p++;
5234
0
    e->text.len = p - e->text.s;
5235
5236
0
    if(!is_in_str(p,in))
5237
0
      break;
5238
0
    s.s = p;
5239
0
    s.len = in->s+in->len-p;
5240
0
    p0 = pv_parse_spec(&s, &e->spec);
5241
5242
0
    if(p0==NULL) {
5243
0
      LM_ERR("parsing PV spec failed\n");
5244
0
      goto error;
5245
0
    }
5246
0
    if(!is_in_str(p0,in))
5247
0
      break;
5248
0
    p = p0;
5249
0
  }
5250
  /*LM_DBG("format parsed OK: [%d] items\n", n);*/
5251
5252
0
  if(*el == NULL)
5253
0
    return -1;
5254
5255
0
  return 0;
5256
5257
0
error:
5258
0
  pv_elem_free_all(*el);
5259
0
  *el = NULL;
5260
0
  return -1;
5261
0
}
5262
5263
int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name)
5264
0
{
5265
0
  if(msg==NULL || ip==NULL || name==NULL)
5266
0
    return -1;
5267
0
  memset(name, 0, sizeof(pv_value_t));
5268
5269
0
  if(ip->pvn.type==PV_NAME_INTSTR)
5270
0
  {
5271
0
    if(ip->pvn.u.isname.type&AVP_NAME_STR)
5272
0
    {
5273
0
      name->rs = ip->pvn.u.isname.name.s;
5274
0
      name->flags = PV_VAL_STR;
5275
0
    } else {
5276
0
      name->ri = ip->pvn.u.isname.name.n;
5277
0
      name->flags = PV_VAL_INT|PV_TYPE_INT;
5278
0
    }
5279
0
    return 0;
5280
0
  }
5281
  /* pvar */
5282
0
  if(pv_get_spec_value(msg, (const pv_spec_p)(ip->pvn.u.dname), name)!=0)
5283
0
  {
5284
0
    LM_ERR("cannot get name value\n");
5285
0
    return -1;
5286
0
  }
5287
0
  if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY)
5288
0
  {
5289
0
    LM_ERR("null or empty name\n");
5290
0
    return -1;
5291
0
  }
5292
0
  return 0;
5293
0
}
5294
5295
int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int *avp_name,
5296
    unsigned short *name_type)
5297
0
{
5298
0
  pv_value_t tv;
5299
0
  if(ip==NULL || avp_name==NULL || name_type==NULL)
5300
0
    return -1;
5301
0
  *avp_name = 0;
5302
0
  *name_type = 0;
5303
5304
0
  if(ip->pvn.type==PV_NAME_INTSTR)
5305
0
  {
5306
0
    *name_type = ip->pvn.u.isname.type;
5307
0
    *avp_name = ip->pvn.u.isname.name.n;
5308
0
    *name_type &= AVP_SCRIPT_MASK;
5309
0
    return 0;
5310
0
  }
5311
  /* pvar */
5312
0
  if(pv_get_spec_value(msg, (const pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
5313
0
  {
5314
0
    LM_ERR("cannot get avp value\n");
5315
0
    return -1;
5316
0
  }
5317
0
  if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
5318
0
  {
5319
0
    LM_ERR("null or empty name\n");
5320
0
    return -1;
5321
0
  }
5322
5323
0
  if(!(tv.flags&PV_VAL_STR))
5324
0
    tv.rs.s = int2str(tv.ri, &tv.rs.len);
5325
5326
  /* search the name here */
5327
0
  *avp_name = get_avp_id(&tv.rs);
5328
0
  if (*avp_name == 0) {
5329
0
    LM_ERR("cannot find avp %.*s\n", tv.rs.len, tv.rs.s);
5330
0
    return -1;
5331
0
  }
5332
0
  return 0;
5333
0
}
5334
5335
5336
int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
5337
0
{
5338
0
  pv_value_t tv;
5339
0
  if(ip==NULL || idx==NULL || flags==NULL)
5340
0
    return -1;
5341
5342
0
  *idx = 0;
5343
0
  *flags = ip->pvi.type;
5344
5345
0
  if(ip->pvi.type == 0)
5346
0
    return 0;
5347
5348
0
  if(ip->pvi.type == PV_IDX_ALL || ip->pvi.type == PV_IDX_APPEND) {
5349
0
    return 0;
5350
0
  }
5351
5352
0
  if(ip->pvi.type == PV_IDX_INT)
5353
0
  {
5354
0
    *idx = ip->pvi.u.ival;
5355
0
    return 0;
5356
0
  }
5357
5358
  /* pvar */
5359
0
  if(pv_get_spec_value(msg, (const pv_spec_p)ip->pvi.u.dval, &tv)!=0)
5360
0
  {
5361
0
    LM_ERR("cannot get index value\n");
5362
0
    return -1;
5363
0
  }
5364
0
  if(!(tv.flags & PV_VAL_INT))
5365
0
  {
5366
0
    LM_ERR("invalid index value\n");
5367
0
    return -1;
5368
0
  }
5369
0
  *idx = tv.ri;
5370
0
  return 0;
5371
0
}
5372
5373
/* function to set pv value */
5374
int pv_set_value(struct sip_msg* msg, pv_spec_p sp,
5375
    int op, pv_value_t *value)
5376
0
{
5377
0
  struct sip_msg* pv_msg;
5378
5379
0
  if(msg==NULL || sp==NULL || sp->setf==NULL || sp->type==PVT_NONE)
5380
0
  {
5381
0
    LM_ERR("bad parameters\n");
5382
0
    return -1;
5383
0
  }
5384
5385
0
  if(sp->pvc && sp->pvc->contextf)
5386
0
  {
5387
0
    pv_msg = sp->pvc->contextf(msg);
5388
0
    if(pv_msg == NULL || pv_msg==FAKED_REPLY)
5389
0
    {
5390
0
      LM_DBG("Invalid %p pv context message\n",pv_msg);
5391
0
      return -1;
5392
0
    }
5393
0
  }
5394
0
  else
5395
0
    pv_msg = msg;
5396
5397
0
  return (*sp->setf)(pv_msg, &(sp->pvp), op, value);
5398
0
}
5399
5400
int pv_get_spec_value(struct sip_msg* msg, const pv_spec_p sp, pv_value_t *value)
5401
0
{
5402
0
  struct sip_msg* pv_msg;
5403
5404
0
  if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
5405
0
      || sp->type==PVT_NONE)
5406
0
  {
5407
0
    LM_ERR("bad parameters\n");
5408
0
    return -1;
5409
0
  }
5410
5411
0
  memset(value, 0, sizeof(pv_value_t));
5412
5413
0
  if(sp->pvc && sp->pvc->contextf)
5414
0
  {
5415
0
    LM_DBG("Found context function %p\n", sp->pvc->contextf);
5416
0
    pv_msg = sp->pvc->contextf(msg);
5417
0
    if(pv_msg == NULL || pv_msg==FAKED_REPLY)
5418
0
    {
5419
0
      LM_DBG("Invalid %p pv context message\n",pv_msg);
5420
0
      return pv_get_null( NULL, NULL, value);
5421
0
    }
5422
0
  } else {
5423
0
    pv_msg = msg;
5424
0
  }
5425
0
  if((*sp->getf)(pv_msg, &(sp->pvp), value)!=0)
5426
0
    return pv_get_null( NULL, NULL, value);
5427
0
  if(sp->trans)
5428
0
    if (run_transformations(pv_msg, (trans_t*)sp->trans, value)!=0)
5429
0
      return pv_get_null( NULL, NULL, value);
5430
0
  return 0;
5431
0
}
5432
5433
int pv_print_spec(struct sip_msg* msg, const pv_spec_p sp, char *buf, int *len)
5434
0
{
5435
0
  pv_value_t tok;
5436
0
  if(msg==NULL || sp==NULL || buf==NULL || len==NULL)
5437
0
    return -1;
5438
5439
0
  if(*len <= 0)
5440
0
    return -1;
5441
5442
0
  memset(&tok, 0, sizeof(pv_value_t));
5443
5444
  /* put the value of the specifier */
5445
0
  if(pv_get_spec_value(msg, sp, &tok)==0)
5446
0
  {
5447
0
    if(tok.flags&PV_VAL_NULL)
5448
0
      tok.rs = str_null;
5449
0
    if(tok.rs.len < *len)
5450
0
      memcpy(buf, tok.rs.s, tok.rs.len);
5451
0
    else
5452
0
      goto overflow;
5453
0
  }
5454
5455
0
  *len = tok.rs.len;
5456
0
  buf[tok.rs.len] = '\0';
5457
0
  return 0;
5458
5459
0
overflow:
5460
0
  LM_ERR("buffer overflow -- increase the buffer size...\n");
5461
0
  return -1;
5462
0
}
5463
5464
5465
int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
5466
0
{
5467
0
  int n;
5468
0
  pv_value_t tok;
5469
0
  str print;
5470
0
  pv_elem_p it;
5471
0
  char *cur;
5472
5473
0
  if(msg==NULL || list==NULL || buf==NULL || len==NULL)
5474
0
    return -1;
5475
5476
0
  if(*len <= 0)
5477
0
    return -1;
5478
5479
0
  *buf = '\0';
5480
0
  cur = buf;
5481
5482
0
  n = 0;
5483
0
  for (it=list; it; it=it->next)
5484
0
  {
5485
    /* put the text */
5486
0
    if(it->text.s && it->text.len>0)
5487
0
    {
5488
0
      if(n+it->text.len < *len)
5489
0
      {
5490
0
        memcpy(cur, it->text.s, it->text.len);
5491
0
        n += it->text.len;
5492
0
        cur += it->text.len;
5493
0
      } else {
5494
0
        LM_ERR("no more space for text [%d][%d]\n", n, it->text.len);
5495
0
        goto overflow;
5496
0
      }
5497
0
    }
5498
    /* put the value of the specifier */
5499
0
    if(it->spec.type!=PVT_NONE
5500
0
        && pv_get_spec_value(msg, &(it->spec), &tok)==0)
5501
0
    {
5502
0
      print = pv_value_print(&tok);
5503
0
      if (n + print.len >= *len) {
5504
0
        LM_ERR("no more space for spec value [%d][%d]\n",
5505
0
               n, print.len);
5506
0
        goto overflow;
5507
0
      }
5508
5509
0
      memcpy(cur, print.s, print.len);
5510
0
      n += print.len;
5511
0
      cur += print.len;
5512
0
    }
5513
0
  }
5514
5515
0
  goto done;
5516
5517
0
overflow:
5518
0
  if (is_pv_print_buf(buf))
5519
0
    LM_ERR("buffer too small -- increase 'pv_print_buf_size' from [%d]\n",
5520
0
        *len);
5521
0
  else
5522
0
    LM_ERR("buffer too small -- increase the buffer size "
5523
0
        "from [%d]...\n", *len);
5524
0
  return -1;
5525
5526
0
done:
5527
#ifdef EXTRA_DEBUG
5528
  LM_DBG("final buffer length %d\n", n);
5529
#endif
5530
0
  *cur = '\0';
5531
0
  *len = n;
5532
0
  return 0;
5533
0
}
5534
5535
5536
5537
pvname_list_t* parse_pvname_list(str *in, unsigned int type)
5538
0
{
5539
0
  pvname_list_t* head = NULL;
5540
0
  pvname_list_t* al = NULL;
5541
0
  pvname_list_t* last = NULL;
5542
0
  char *p;
5543
0
  pv_spec_t spec;
5544
0
  str s;
5545
5546
0
  if(in==NULL || in->s==NULL)
5547
0
  {
5548
0
    LM_ERR("bad parameters\n");
5549
0
    return NULL;
5550
0
  }
5551
5552
0
  p = in->s;
5553
0
  while(is_in_str(p, in))
5554
0
  {
5555
0
    while(is_in_str(p, in) && (is_ws(*p)||*p==','||*p==';'))
5556
0
      p++;
5557
0
    if(!is_in_str(p, in))
5558
0
    {
5559
0
      if(head==NULL)
5560
0
        LM_ERR("wrong item name list [%.*s]\n", in->len, in->s);
5561
0
      return head;
5562
0
    }
5563
0
    s.s=p;
5564
0
    s.len = in->s+in->len-p;
5565
0
    p = pv_parse_spec(&s, &spec);
5566
0
    if(p==NULL || (type && spec.type!=type))
5567
0
    {
5568
0
      LM_ERR("wrong item name list [%.*s]!\n", in->len, in->s);
5569
0
      goto error;
5570
0
    }
5571
0
    al = (pvname_list_t*)pkg_malloc(sizeof(pvname_list_t));
5572
0
    if(al==NULL)
5573
0
    {
5574
0
      LM_ERR("no more memory!\n");
5575
0
      goto error;
5576
0
    }
5577
0
    memset(al, 0, sizeof(pvname_list_t));
5578
0
    memcpy(&al->sname, &spec, sizeof(pv_spec_t));
5579
5580
0
    if(last==NULL)
5581
0
    {
5582
0
      head = al;
5583
0
      last = al;
5584
0
    } else {
5585
0
      last->next = al;
5586
0
      last = al;
5587
0
    }
5588
0
  }
5589
5590
0
  return head;
5591
5592
0
error:
5593
0
  while(head)
5594
0
  {
5595
0
    al = head;
5596
0
    head=head->next;
5597
0
    pkg_free(al);
5598
0
  }
5599
0
  return NULL;
5600
0
}
5601
5602
int pv_elem_free_all(pv_elem_p log)
5603
0
{
5604
0
  pv_elem_p t;
5605
0
  while(log)
5606
0
  {
5607
0
    t = log;
5608
0
    log = log->next;
5609
5610
0
    if (t->spec.trans)
5611
0
      free_transformation((trans_t *)t->spec.trans);
5612
0
    pkg_free(t);
5613
0
  }
5614
0
  return 0;
5615
0
}
5616
5617
static str pv_value_print(const pv_value_t *val)
5618
0
{
5619
0
  str printed = str_init(NULL);
5620
5621
0
  if (val->flags & PV_VAL_NULL)
5622
0
    return str_null;
5623
5624
0
  if (val->flags & PV_VAL_STR)
5625
0
    return val->rs;
5626
5627
0
  if (val->flags & (PV_VAL_INT|PV_TYPE_INT)) {
5628
0
    printed.s = int2str(val->ri, &printed.len);
5629
0
    return printed;
5630
0
  }
5631
5632
0
  LM_ERR("unknown type %x\n", val->flags);
5633
0
  return str_empty;
5634
0
}
5635
5636
void pv_value_destroy(pv_value_t *val)
5637
0
{
5638
0
  if(val==0) return;
5639
0
  if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
5640
0
  if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
5641
0
  memset(val, 0, sizeof(pv_value_t));
5642
0
}
5643
5644
/* IMPORTANT NOTE - even if the function prints and returns a static buffer, it
5645
 * has built-in support for PV_PRINTF_BUF_NO levels of nesting
5646
 * (or concurrent usage).  If you think it's not enough for you, either use
5647
 * pv_printf() directly, either increase PV_PRINT_BUF_NO   --bogdan */
5648
int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
5649
0
{
5650
0
  static int buf_itr = 0;
5651
5652
0
  if (list->next==0 && list->spec.getf==0) {
5653
0
    *s = list->text;
5654
0
    return 0;
5655
0
  } else {
5656
0
    *s = pv_print_buf[buf_itr];
5657
0
    buf_itr = (buf_itr + 1) % PV_PRINT_BUF_NO;
5658
0
    return pv_printf(msg, list, s->s, &s->len);
5659
0
  }
5660
0
}
5661
5662
void pv_spec_free(pv_spec_t *spec)
5663
0
{
5664
0
  if(spec==0) return;
5665
  /* TODO: free name if it is PV */
5666
0
  if(spec->trans)
5667
0
    free_transformation((trans_t*)spec->trans);
5668
0
  pkg_free(spec);
5669
0
}
5670
5671
int pv_spec_dbg(const pv_spec_p sp)
5672
0
{
5673
0
  if(sp==NULL)
5674
0
  {
5675
0
    LM_DBG("spec: <<NULL>>\n");
5676
0
    return 0;
5677
0
  }
5678
0
  LM_DBG("<spec>\n");
5679
0
  LM_DBG("type: %d\n", sp->type);
5680
0
  LM_DBG("getf: %p\n", sp->getf);
5681
0
  LM_DBG("setf: %p\n", sp->setf);
5682
0
  LM_DBG("tran: %p\n", sp->trans);
5683
0
  LM_DBG("<param>\n");
5684
0
  LM_DBG("<name>\n");
5685
0
  LM_DBG("type: %d\n", sp->pvp.pvn.type);
5686
0
  if(sp->pvp.pvn.type==PV_NAME_INTSTR)
5687
0
  {
5688
0
    LM_DBG("sub-type: %d\n", sp->pvp.pvn.u.isname.type);
5689
0
    if (sp->pvp.pvn.u.isname.type&AVP_NAME_STR)
5690
0
    {
5691
0
      LM_DBG("name str: %.*s\n",
5692
0
          sp->pvp.pvn.u.isname.name.s.len,
5693
0
          sp->pvp.pvn.u.isname.name.s.s);
5694
0
    } else {
5695
0
      LM_DBG("name in: %d\n",
5696
0
          sp->pvp.pvn.u.isname.name.n);
5697
0
    }
5698
5699
0
  } else if(sp->pvp.pvn.type==PV_NAME_PVAR) {
5700
0
    pv_spec_dbg((pv_spec_p)sp->pvp.pvn.u.dname);
5701
0
  } else {
5702
0
    LM_DBG("name: unknown\n");
5703
0
  }
5704
0
  LM_DBG("</name>\n");
5705
0
  LM_DBG("<index>\n");
5706
0
  LM_DBG("type: %d\n", sp->pvp.pvi.type);
5707
0
  if(sp->pvp.pvi.type==PV_IDX_INT)
5708
0
  {
5709
0
    LM_DBG("index: %d\n", sp->pvp.pvi.u.ival);
5710
0
  } else if(sp->pvp.pvi.type==PV_IDX_PVAR) {
5711
0
    pv_spec_dbg((pv_spec_p)sp->pvp.pvi.u.dval);
5712
0
  } else if(sp->pvp.pvi.type==PV_IDX_ALL){
5713
0
    LM_DBG("index: *\n");
5714
0
  } else {
5715
0
    LM_DBG("index: unknown\n");
5716
0
  }
5717
0
  LM_DBG("</index>\n");
5718
0
  LM_DBG("</param>\n");
5719
0
  LM_DBG("</spec\n");
5720
0
  return 0;
5721
0
}
5722
5723
5724
/**
5725
 *
5726
 */
5727
static int pv_init_extra_list(void)
5728
0
{
5729
0
  _pv_extra_list = (pv_extra_p*)pkg_malloc(sizeof(pv_extra_p));
5730
0
  if(_pv_extra_list==0)
5731
0
  {
5732
0
    LM_ERR("cannot alloc extra items list\n");
5733
0
    return -1;
5734
0
  }
5735
0
  *_pv_extra_list=0;
5736
0
  return 0;
5737
0
}
5738
5739
static int pv_add_extra(const pv_export_t *e)
5740
0
{
5741
0
  const char *p;
5742
0
  const str_const *in;
5743
0
  pv_extra_t *pvi = NULL;
5744
0
  pv_extra_t *pvj = NULL;
5745
0
  pv_extra_t *pvn = NULL;
5746
0
  int found;
5747
5748
0
  if(e==NULL || e->name.s==NULL || e->getf==NULL || e->type==PVT_NONE)
5749
0
  {
5750
0
    LM_ERR("invalid parameters\n");
5751
0
    return -1;
5752
0
  }
5753
5754
0
  if(_pv_extra_list==0)
5755
0
  {
5756
0
    LM_DBG("extra items list is not initialized\n");
5757
0
    if(pv_init_extra_list()!=0)
5758
0
    {
5759
0
      LM_ERR("cannot intit extra list\n");
5760
0
      return -1;
5761
0
    }
5762
0
  }
5763
0
  in = &(e->name);
5764
0
  p = in->s;
5765
0
  while(is_in_str(p,in) && is_pv_valid_char(*p))
5766
0
    p++;
5767
0
  if(is_in_str(p,in))
5768
0
  {
5769
0
    LM_ERR("invalid char [%c] in [%.*s]\n", *p, in->len, in->s);
5770
0
    return -1;
5771
0
  }
5772
0
  found = 0;
5773
0
  pvi = *_pv_extra_list;
5774
0
  while(pvi)
5775
0
  {
5776
0
    if(pvi->pve.name.len > in->len)
5777
0
      break;
5778
0
    if(pvi->pve.name.len==in->len)
5779
0
    {
5780
0
      found = strncmp(pvi->pve.name.s, in->s, in->len);
5781
0
      if(found>0)
5782
0
        break;
5783
0
      if(found==0)
5784
0
      {
5785
0
        LM_ERR("pvar [%.*s] already exists\n", in->len, in->s);
5786
0
        return -1;
5787
0
      }
5788
0
    }
5789
0
    pvj = pvi;
5790
0
    pvi = pvi->next;
5791
0
  }
5792
5793
0
  pvn = (pv_extra_t*)pkg_malloc(sizeof(pv_extra_t));
5794
0
  if(pvn==0)
5795
0
  {
5796
0
    LM_ERR("no more memory\n");
5797
0
    return -1;
5798
0
  }
5799
0
  memcpy(&pvn->pve, e, sizeof(*e));
5800
0
  pvn->pve.type += PVT_EXTRA;
5801
5802
0
  if(pvj==0)
5803
0
  {
5804
0
    pvn->next = *_pv_extra_list;
5805
0
    *_pv_extra_list = pvn;
5806
0
    goto done;
5807
0
  }
5808
0
  pvn->next = pvj->next;
5809
0
  pvj->next = pvn;
5810
5811
0
done:
5812
0
  return 0;
5813
0
}
5814
5815
int register_pvars_mod(const char *mod_name, const pv_export_t *items)
5816
0
{
5817
0
  int ret;
5818
0
  int i;
5819
5820
0
  if (items==0)
5821
0
    return 0;
5822
5823
0
  for ( i=0 ; items[i].name.s ; i++ ) {
5824
0
    ret = pv_add_extra(&items[i]);
5825
0
    if (ret!=0) {
5826
0
      LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
5827
0
          items[i].name.len, items[i].name.s, mod_name);
5828
0
    }
5829
0
  }
5830
0
  return 0;
5831
0
}
5832
5833
/**
5834
 *
5835
 */
5836
int pv_free_extra_list(void)
5837
0
{
5838
0
  pv_extra_p xe;
5839
0
  pv_extra_p xe1;
5840
0
  if(_pv_extra_list!=0)
5841
0
  {
5842
0
    xe = *_pv_extra_list;
5843
0
    while(xe!=0)
5844
0
    {
5845
0
      xe1 = xe;
5846
0
      xe = xe->next;
5847
0
      pkg_free(xe1);
5848
0
    }
5849
0
    pkg_free(_pv_extra_list);
5850
0
    _pv_extra_list = 0;
5851
0
  }
5852
5853
0
  return 0;
5854
0
}
5855
5856
static pv_context_t* new_pv_context(const str* name, pv_contextf_t get_context)
5857
0
{
5858
0
  pv_context_t* pvc_new = NULL;
5859
0
  int size;
5860
/*
5861
  if(get_context == NULL)
5862
  {
5863
    LM_ERR("NULL pointer to function\n");
5864
    return 0;
5865
  }
5866
*/
5867
0
  size = sizeof(pv_context_t) + name->len;
5868
0
  pvc_new = (pv_context_t*)pkg_malloc(size);
5869
0
  if(pvc_new == NULL)
5870
0
  {
5871
0
    LM_ERR("No more memory\n");
5872
0
    return 0;
5873
0
  }
5874
0
  memset(pvc_new, 0, size);
5875
5876
0
  pvc_new->name.s = (char*)pvc_new + sizeof(pv_context_t);
5877
0
  memcpy(pvc_new->name.s, name->s, name->len);
5878
0
  pvc_new->name.len = name->len;
5879
5880
0
  pvc_new->contextf = get_context;
5881
5882
0
  return pvc_new;
5883
0
}
5884
5885
int register_pv_context(char* cname, pv_contextf_t get_context)
5886
0
{
5887
0
  pv_context_t* pvc = pv_context_lst;
5888
0
  str name;
5889
5890
0
  if(cname == NULL)
5891
0
  {
5892
0
    LM_DBG("NULL parameter\n");
5893
0
    return -1;
5894
0
  }
5895
5896
0
  name.s = cname;
5897
0
  name.len = strlen(cname);
5898
5899
0
  LM_DBG("Registered new context: %.*s / %p\n", name.len, name.s, get_context);
5900
0
  pvc = pv_get_context(&name);
5901
0
  if(pvc == NULL)
5902
0
  {
5903
0
    LM_DBG("Context not found\n");
5904
0
    if(add_pv_context(&name, get_context) == NULL)
5905
0
    {
5906
0
      LM_ERR("Failed to add context\n");
5907
0
      return -1;
5908
0
    }
5909
0
    return 1;
5910
0
  }
5911
5912
0
  if(pvc->contextf!=NULL)
5913
0
  {
5914
0
    LM_ERR("Context already registered [%s]\n", cname);
5915
0
    return -1;
5916
0
  }
5917
0
  if(get_context == NULL)
5918
0
  {
5919
0
    LM_ERR("NULL context getter function\n");
5920
0
    return -1;
5921
0
  }
5922
0
  pvc->contextf= get_context;
5923
0
  return 1;
5924
0
}
5925
5926
5927
/* function to register a pv context getter */
5928
static pv_context_t* add_pv_context(const str* name, pv_contextf_t get_context)
5929
0
{
5930
0
  pv_context_t* pvc = pv_context_lst;
5931
0
  pv_context_t* pvc_new, *pvc_prev;
5932
5933
0
  if(pvc == NULL)
5934
0
  {
5935
0
    pvc_new = new_pv_context(name, get_context);
5936
0
    if(pvc_new == NULL)
5937
0
    {
5938
0
      LM_ERR("Failed to allocate context\n");
5939
0
      return 0;
5940
0
    }
5941
0
    pv_context_lst = pvc_new;
5942
0
    return pvc_new;
5943
0
  }
5944
5945
0
  while(pvc)
5946
0
  {
5947
0
    if(pvc->name.len == name->len && strncmp(pvc->name.s, name->s, name->len)==0)
5948
0
    {
5949
0
      LM_ERR("PV Context already registered [%.*s]\n", name->len, name->s);
5950
0
      return 0;
5951
0
    }
5952
0
    pvc_prev = pvc;
5953
0
    pvc = pvc->next;
5954
0
  }
5955
5956
0
  pvc_new = new_pv_context(name, get_context);
5957
0
  if(pvc_new == NULL)
5958
0
  {
5959
0
    LM_ERR("Failed to allocate context\n");
5960
0
    return 0;
5961
0
  }
5962
5963
0
  LM_DBG("Registered new context: %.*s\n", name->len, name->s);
5964
5965
0
  pvc_prev->next = pvc_new;
5966
5967
0
  return pvc_new;
5968
0
}
5969
5970
static pv_context_t* pv_get_context(const str* name)
5971
0
{
5972
0
  pv_context_t* pvc = pv_context_lst;
5973
5974
0
  while(pvc)
5975
0
  {
5976
0
    if(pvc->name.len == name->len &&
5977
0
        strncmp(pvc->name.s, name->s, name->len) == 0)
5978
0
    {
5979
0
      return pvc;
5980
0
    }
5981
0
    pvc = pvc->next;
5982
0
  }
5983
0
  return 0;
5984
0
}
5985
5986
static int pv_contextlist_check(void)
5987
0
{
5988
0
  pv_context_t* pvc = pv_context_lst;
5989
5990
0
  while(pvc)
5991
0
  {
5992
0
    if(pvc->contextf == NULL)
5993
0
      return -1;
5994
5995
0
    pvc = pvc->next;
5996
0
  }
5997
0
  pvc_before_check = 0;
5998
0
  return 0;
5999
0
}
6000
6001
/* argument options '-o' */
6002
argv_p argv_vars = NULL;
6003
6004
static argv_p search_argv(const str *name)
6005
0
{
6006
0
  argv_p it;
6007
6008
0
  for (it = argv_vars; it; it = it->next) {
6009
0
    if (it->name.len == name->len &&
6010
0
        !strncmp(it->name.s, name->s, name->len))
6011
0
      return it;
6012
0
  }
6013
0
  return 0;
6014
0
}
6015
6016
int add_arg_var(char *opt)
6017
0
{
6018
0
  char *eq;
6019
0
  str name;
6020
0
  argv_p new = NULL;
6021
6022
0
  if (!opt) {
6023
0
    LM_ERR("cannot receive null option\n");
6024
0
    return -1;
6025
0
  }
6026
6027
0
  eq = strchr(opt, '=');
6028
0
  if (!eq) {
6029
0
    LM_ERR("invalid option format - '=' char cannot be found\n");
6030
0
    return -1;
6031
0
  }
6032
0
  if (eq <= opt) {
6033
0
    LM_ERR("no option name specified\n");
6034
0
    return -1;
6035
0
  }
6036
6037
0
  name.s = opt;
6038
0
  name.len = eq - name.s;
6039
6040
  /* check for duplicate option name */
6041
0
  if (search_argv(&name)) {
6042
0
    LM_ERR("duplicate option name <%.*s>\n", name.len, name.s);
6043
0
    return -1;
6044
0
  }
6045
6046
0
  new = (argv_p)pkg_malloc(sizeof(argv_t));
6047
0
  if (!new) {
6048
0
    LM_ERR("no more pkg memory\n");
6049
0
    return -1;
6050
0
  }
6051
0
  memset(new, 0, sizeof(argv_t));
6052
6053
0
  new->name.s = name.s;
6054
0
  new->name.len = name.len;
6055
6056
0
  new->value.s = eq+1;
6057
0
  new->value.len = strlen(opt) + opt - new->value.s;
6058
6059
0
  if (!new->value.len)
6060
0
    new->value.s = 0;
6061
6062
0
  new->next = argv_vars;
6063
0
  argv_vars = new;
6064
6065
0
  LM_DBG("added argument name <%.*s> = <%.*s>\n",
6066
0
      name.len, name.s, new->value.len, new->value.s);
6067
0
  return 0;
6068
6069
0
}
6070
6071
static int pv_parse_argv_name(pv_spec_p sp, const str *in)
6072
0
{
6073
0
  argv_p v_arg;
6074
6075
0
  if(in==NULL || in->s==NULL || sp==NULL)
6076
0
    return -1;
6077
6078
0
  v_arg = search_argv(in);
6079
0
  if (!v_arg) {
6080
0
    LM_DBG("$argv(%.*s) not found\n", in->len, in->s);
6081
0
    sp->pvp.pvv.len = 0;
6082
0
    sp->pvp.pvv.s = 0;
6083
0
  } else {
6084
0
    sp->pvp.pvv = v_arg->value;
6085
0
    sp->pvp.pvn.u.isname.name.s = v_arg->name;
6086
0
  }
6087
6088
0
  sp->pvp.pvn.type = PV_NAME_PVAR;
6089
6090
0
  return 0;
6091
0
}
6092
6093
static int pv_get_argv(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
6094
0
{
6095
0
  if (!param) {
6096
0
    LM_ERR("null parameter received\n");
6097
0
    return -1;
6098
0
  }
6099
6100
0
  if (param->pvv.len == 0 || !param->pvv.s)
6101
0
    return pv_get_null(msg, param, res);
6102
6103
0
  return pv_get_strval(msg, param, res, &param->pvv);
6104
0
}
6105
6106
static int pv_parse_param_name(pv_spec_p sp, const str *in)
6107
0
{
6108
0
  char *p;
6109
0
  char *s;
6110
0
  pv_spec_p nsp = 0;
6111
6112
0
  if(in==NULL || in->s==NULL || sp==NULL)
6113
0
    return -1;
6114
0
  p = in->s;
6115
0
  if(*p==PV_MARKER)
6116
0
  {
6117
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
6118
0
    if(nsp==NULL)
6119
0
    {
6120
0
      LM_ERR("no more memory\n");
6121
0
      return -1;
6122
0
    }
6123
0
    s = pv_parse_spec(in, nsp);
6124
0
    if(s==NULL)
6125
0
    {
6126
0
      LM_ERR("invalid name [%.*s]\n", in->len, in->s);
6127
0
      pv_spec_free(nsp);
6128
0
      return -1;
6129
0
    }
6130
0
    sp->pvp.pvn.type = PV_NAME_PVAR;
6131
0
    sp->pvp.pvn.u.dname = (void*)nsp;
6132
0
    return 0;
6133
0
  }
6134
  /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
6135
  /* always an int type from now */
6136
0
  sp->pvp.pvn.u.isname.type = 0;
6137
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
6138
  /* do our best to convert it to an index */
6139
0
  if (str2int(in, (unsigned int *)&sp->pvp.pvn.u.isname.name.n) < 0)
6140
0
  {
6141
    /* remember it was a string, so we can retrieve it later */
6142
0
    sp->pvp.pvn.u.isname.name.s = *in;
6143
0
    sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
6144
0
  }
6145
0
  return 0;
6146
6147
0
}
6148
6149
static int pv_parse_return_value(pv_spec_p sp, const str *in)
6150
0
{
6151
0
  char *p;
6152
0
  char *s;
6153
0
  pv_spec_p nsp = 0;
6154
6155
0
  if(in==NULL || in->s==NULL || sp==NULL)
6156
0
    return -1;
6157
0
  p = in->s;
6158
0
  if(*p==PV_MARKER)
6159
0
  {
6160
0
    nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
6161
0
    if(nsp==NULL)
6162
0
    {
6163
0
      LM_ERR("no more memory\n");
6164
0
      return -1;
6165
0
    }
6166
0
    s = pv_parse_spec(in, nsp);
6167
0
    if(s==NULL)
6168
0
    {
6169
0
      LM_ERR("invalid name [%.*s]\n", in->len, in->s);
6170
0
      pv_spec_free(nsp);
6171
0
      return -1;
6172
0
    }
6173
0
    sp->pvp.pvn.type = PV_NAME_PVAR;
6174
0
    sp->pvp.pvn.u.dname = (void*)nsp;
6175
0
    return 0;
6176
0
  }
6177
0
  sp->pvp.pvn.u.isname.type = 0;
6178
0
  sp->pvp.pvn.type = PV_NAME_INTSTR;
6179
  /* do our best to convert it to an index */
6180
0
  if (str2int(in, (unsigned int *)&sp->pvp.pvn.u.isname.name.n) < 0) {
6181
0
    LM_ERR("could not convert index to int!\n");
6182
0
    return -1;
6183
0
  }
6184
0
  return 0;
6185
6186
0
}
6187
6188
static int pv_get_param(struct sip_msg *msg,  pv_param_t *ip, pv_value_t *res)
6189
0
{
6190
0
  if (!ip)
6191
0
  {
6192
0
    LM_ERR("null parameter received\n");
6193
0
    return -1;
6194
0
  }
6195
0
  return route_params_run(msg, ip, res);
6196
0
}
6197
6198
void destroy_argv_list(void)
6199
0
{
6200
0
  argv_p arg;
6201
6202
0
  while (argv_vars) {
6203
0
    arg = argv_vars;
6204
0
    argv_vars = argv_vars->next;
6205
0
    pkg_free(arg);
6206
0
  }
6207
0
}