Coverage Report

Created: 2025-07-18 06:41

/src/kamailio/src/core/dset.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * destination set
3
 *
4
 * Copyright (C) 2001-2004 FhG FOKUS
5
 *
6
 * This file is part of Kamailio, a free SIP server.
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 *
10
 * Kamailio is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version
14
 *
15
 * Kamailio is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23
 */
24
25
/** Kamailio core :: destination set / branches support.
26
 * @file dset.c
27
 * @ingroup core
28
 * Module: @ref core
29
 */
30
31
#include <string.h>
32
#include "dprint.h"
33
#include "config.h"
34
#include "parser/parser_f.h"
35
#include "parser/parse_uri.h"
36
#include "parser/parse_param.h"
37
#include "parser/msg_parser.h"
38
#include "globals.h"
39
#include "ut.h"
40
#include "hash_func.h"
41
#include "error.h"
42
#include "dset.h"
43
#include "mem/mem.h"
44
#include "ip_addr.h"
45
#include "strutils.h"
46
47
0
#define CONTACT "Contact: "
48
0
#define CONTACT_LEN (sizeof(CONTACT) - 1)
49
50
0
#define CONTACT_DELIM ", "
51
0
#define CONTACT_DELIM_LEN (sizeof(CONTACT_DELIM) - 1)
52
53
0
#define Q_PARAM ";q="
54
0
#define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
55
56
0
#define ROUTE_PARAM "?Route="
57
0
#define ROUTE_PARAM_LEN (sizeof(ROUTE_PARAM) - 1)
58
59
0
#define FLAGS_PARAM ";flags="
60
0
#define FLAGS_PARAM_LEN (sizeof(FLAGS_PARAM) - 1)
61
62
/*
63
 * Where we store URIs of additional transaction branches
64
 * (sr_dst_max_branches - 1 : because of the default branch for r-uri, #0 in tm)
65
 */
66
static branch_t *_ksr_branches = NULL;
67
68
/* how many of them we have */
69
unsigned int nr_branches = 0;
70
71
/* branch iterator */
72
static int branch_iterator = 0;
73
74
/* used to mark ruris "consumed" when branching (1 new, 0 consumed) */
75
int ruri_is_new = 0;
76
77
/* The q parameter of the Request-URI */
78
static qvalue_t ruri_q = Q_UNSPECIFIED;
79
80
/* Branch flags of the Request-URI */
81
static flag_t ruri_bflags;
82
83
/* alias parameter for contact uri/r-uri with surrounding semicolon or =
84
 * - used for set_contact_alias()/handle_ruri_alias() */
85
str _ksr_contact_alias = str_init("alias=");
86
str _ksr_contact_salias = str_init(";alias=");
87
88
/**
89
 *
90
 */
91
int init_dst_set(void)
92
0
{
93
0
  if(sr_dst_max_branches <= 0 || sr_dst_max_branches >= MAX_BRANCHES_LIMIT) {
94
0
    LM_ERR("invalid value for max branches parameter: %u, maximum value: "
95
0
         "%u\n",
96
0
        sr_dst_max_branches, MAX_BRANCHES_LIMIT);
97
0
    return -1;
98
0
  }
99
  /* sr_dst_max_branches - 1 : because of the default branch for r-uri, #0 in tm */
100
0
  _ksr_branches = (branch_t *)pkg_malloc(
101
0
      (sr_dst_max_branches - 1) * sizeof(branch_t));
102
0
  if(_ksr_branches == NULL) {
103
0
    PKG_MEM_ERROR;
104
0
    return -1;
105
0
  }
106
0
  memset(_ksr_branches, 0, (sr_dst_max_branches - 1) * sizeof(branch_t));
107
0
  return 0;
108
0
}
109
110
/**
111
 *
112
 */
113
unsigned int get_nr_branches(void)
114
0
{
115
0
  return nr_branches;
116
0
}
117
118
/*! \brief
119
 * Return pointer to branch[idx] structure
120
 * @param idx - branch index
121
 *
122
 * @return  pointer to branch or NULL if invalid branch
123
 */
124
branch_t *get_sip_branch(int idx)
125
0
{
126
0
  if(nr_branches == 0)
127
0
    return NULL;
128
0
  if(idx < 0) {
129
0
    if((int)nr_branches + idx >= 0)
130
0
      return &_ksr_branches[nr_branches + idx];
131
0
    return NULL;
132
0
  }
133
0
  if(idx < nr_branches)
134
0
    return &_ksr_branches[idx];
135
0
  return 0;
136
0
}
137
138
/**
139
 *
140
 */
141
int get_all_sip_branches(branch_t **vbranches, unsigned int *nbranches)
142
0
{
143
0
  if(nr_branches == 0) {
144
0
    *vbranches = NULL;
145
0
    *nbranches = 0;
146
0
    return 0;
147
0
  }
148
149
0
  *vbranches = (branch_t *)pkg_malloc(nr_branches * sizeof(branch_t));
150
0
  if(*vbranches == NULL) {
151
0
    PKG_MEM_ERROR;
152
0
    return -1;
153
0
  }
154
0
  memcpy(*vbranches, _ksr_branches, nr_branches * sizeof(branch_t));
155
0
  *nbranches = nr_branches;
156
157
0
  return 0;
158
0
}
159
160
/**
161
 *
162
 */
163
int set_all_sip_branches(branch_t *vbranches, unsigned int nbranches)
164
0
{
165
0
  if(nbranches == 0) {
166
0
    nr_branches = 0;
167
0
    return 0;
168
0
  }
169
170
0
  memcpy(_ksr_branches, vbranches, nbranches * sizeof(branch_t));
171
0
  nr_branches = nbranches;
172
173
0
  return 0;
174
0
}
175
176
/*! \brief
177
 * Drop branch[idx]
178
 * @param idx - branch index
179
 *
180
 * @return  0 on success, -1 on error
181
 */
182
int drop_sip_branch(int idx)
183
0
{
184
0
  if(nr_branches == 0 || idx >= nr_branches)
185
0
    return 0;
186
0
  if(idx < 0 && (int)nr_branches + idx < 0)
187
0
    return 0;
188
0
  if(idx < 0)
189
0
    idx += nr_branches;
190
  /* last branch */
191
0
  if(idx == nr_branches - 1) {
192
0
    nr_branches--;
193
0
    return 0;
194
0
  }
195
  /* shift back one position */
196
0
  for(; idx < nr_branches - 1; idx++)
197
0
    memcpy(&_ksr_branches[idx], &_ksr_branches[idx + 1], sizeof(branch_t));
198
0
  nr_branches--;
199
0
  return 0;
200
0
}
201
202
static inline flag_t *get_bflags_ptr(unsigned int branch)
203
0
{
204
0
  if(branch == 0)
205
0
    return &ruri_bflags;
206
0
  if(branch - 1 < nr_branches)
207
0
    return &_ksr_branches[branch - 1].flags;
208
0
  return NULL;
209
0
}
210
211
212
int setbflag(unsigned int branch, flag_t flag)
213
0
{
214
0
  flag_t *flags;
215
216
0
  if((flags = get_bflags_ptr(branch)) == NULL)
217
0
    return -1;
218
0
  (*flags) |= 1 << flag;
219
0
  return 1;
220
0
}
221
222
223
int isbflagset(unsigned int branch, flag_t flag)
224
0
{
225
0
  flag_t *flags;
226
227
0
  if((flags = get_bflags_ptr(branch)) == NULL)
228
0
    return -1;
229
0
  return ((*flags) & (1 << flag)) ? 1 : -1;
230
0
}
231
232
233
int resetbflag(unsigned int branch, flag_t flag)
234
0
{
235
0
  flag_t *flags;
236
237
0
  if((flags = get_bflags_ptr(branch)) == NULL)
238
0
    return -1;
239
0
  (*flags) &= ~(1 << flag);
240
0
  return 1;
241
0
}
242
243
244
int getbflagsval(unsigned int branch, flag_t *res)
245
0
{
246
0
  flag_t *flags;
247
0
  if(res == NULL)
248
0
    return -1;
249
0
  if((flags = get_bflags_ptr(branch)) == NULL)
250
0
    return -1;
251
0
  *res = *flags;
252
0
  return 1;
253
0
}
254
255
256
int setbflagsval(unsigned int branch, flag_t val)
257
0
{
258
0
  flag_t *flags;
259
0
  if((flags = get_bflags_ptr(branch)) == NULL)
260
0
    return -1;
261
0
  *flags = val;
262
0
  return 1;
263
0
}
264
265
266
/*
267
 * Initialize the branch iterator, the next
268
 * call to next_branch will return the first
269
 * contact from the dset array
270
 */
271
void init_branch_iterator(void)
272
0
{
273
0
  branch_iterator = 0;
274
0
}
275
276
/**
277
 * return the value of current branch iterator
278
 */
279
int get_branch_iterator(void)
280
0
{
281
0
  return branch_iterator;
282
0
}
283
284
/**
285
 * set the value of current branch interator
286
 */
287
void set_branch_iterator(int n)
288
0
{
289
0
  branch_iterator = n;
290
0
}
291
292
293
/** \brief Get a branch from the destination set
294
 * \return Return the 'i' branch from the dset
295
 * array, 0 is returned if there are no
296
 * more branches
297
 */
298
char *get_branch(unsigned int i, int *len, qvalue_t *q, str *dst_uri, str *path,
299
    unsigned int *flags, struct socket_info **force_socket, str *ruid,
300
    str *instance, str *location_ua)
301
0
{
302
0
  if(i < nr_branches) {
303
0
    *len = _ksr_branches[i].len;
304
0
    *q = _ksr_branches[i].q;
305
0
    if(dst_uri) {
306
0
      dst_uri->len = _ksr_branches[i].dst_uri_len;
307
0
      dst_uri->s = (dst_uri->len) ? _ksr_branches[i].dst_uri : 0;
308
0
    }
309
0
    if(path) {
310
0
      path->len = _ksr_branches[i].path_len;
311
0
      path->s = (path->len) ? _ksr_branches[i].path : 0;
312
0
    }
313
0
    if(force_socket)
314
0
      *force_socket = _ksr_branches[i].force_send_socket;
315
0
    if(flags)
316
0
      *flags = _ksr_branches[i].flags;
317
0
    if(ruid) {
318
0
      ruid->len = _ksr_branches[i].ruid_len;
319
0
      ruid->s = (ruid->len) ? _ksr_branches[i].ruid : 0;
320
0
    }
321
0
    if(instance) {
322
0
      instance->len = _ksr_branches[i].instance_len;
323
0
      instance->s = (instance->len) ? _ksr_branches[i].instance : 0;
324
0
    }
325
0
    if(location_ua) {
326
0
      location_ua->len = _ksr_branches[i].location_ua_len;
327
0
      location_ua->s =
328
0
          (location_ua->len) ? _ksr_branches[i].location_ua : 0;
329
0
    }
330
0
    return _ksr_branches[i].uri;
331
0
  } else {
332
0
    *len = 0;
333
0
    *q = Q_UNSPECIFIED;
334
0
    if(dst_uri) {
335
0
      dst_uri->s = 0;
336
0
      dst_uri->len = 0;
337
0
    }
338
0
    if(path) {
339
0
      path->s = 0;
340
0
      path->len = 0;
341
0
    }
342
0
    if(force_socket)
343
0
      *force_socket = 0;
344
0
    if(flags)
345
0
      *flags = 0;
346
0
    if(ruid) {
347
0
      ruid->s = 0;
348
0
      ruid->len = 0;
349
0
    }
350
0
    if(instance) {
351
0
      instance->s = 0;
352
0
      instance->len = 0;
353
0
    }
354
0
    if(location_ua) {
355
0
      location_ua->s = 0;
356
0
      location_ua->len = 0;
357
0
    }
358
0
    return 0;
359
0
  }
360
0
}
361
362
363
/** Return the next branch from the dset array.
364
 * 0 is returned if there are no more branches
365
 */
366
char *next_branch(int *len, qvalue_t *q, str *dst_uri, str *path,
367
    unsigned int *flags, struct socket_info **force_socket, str *ruid,
368
    str *instance, str *location_ua)
369
0
{
370
0
  char *ret;
371
372
0
  ret = get_branch(branch_iterator, len, q, dst_uri, path, flags,
373
0
      force_socket, ruid, instance, location_ua);
374
0
  if(likely(ret))
375
0
    branch_iterator++;
376
0
  return ret;
377
0
}
378
379
/**
380
 * Link branch attributes in the data structure
381
 * - return: -1 (<0) on error; 0 - on no valid branch; 1 - on a valid branch
382
 */
383
int get_branch_data(unsigned int i, branch_data_t *vbranch)
384
0
{
385
0
  if(vbranch == NULL) {
386
0
    return -1;
387
0
  }
388
0
  memset(vbranch, 0, sizeof(branch_data_t));
389
390
0
  if(i < nr_branches) {
391
0
    vbranch->uri.s = _ksr_branches[i].uri;
392
0
    vbranch->uri.len = _ksr_branches[i].len;
393
0
    vbranch->q = _ksr_branches[i].q;
394
0
    if(_ksr_branches[i].dst_uri_len > 0) {
395
0
      vbranch->dst_uri.len = _ksr_branches[i].dst_uri_len;
396
0
      vbranch->dst_uri.s = _ksr_branches[i].dst_uri;
397
0
    }
398
0
    if(_ksr_branches[i].path_len > 0) {
399
0
      vbranch->path.len = _ksr_branches[i].path_len;
400
0
      vbranch->path.s = _ksr_branches[i].path;
401
0
    }
402
0
    vbranch->force_socket = _ksr_branches[i].force_send_socket;
403
0
    vbranch->flags = _ksr_branches[i].flags;
404
0
    if(_ksr_branches[i].ruid_len > 0) {
405
0
      vbranch->ruid.len = _ksr_branches[i].ruid_len;
406
0
      vbranch->ruid.s = _ksr_branches[i].ruid;
407
0
    }
408
0
    if(_ksr_branches[i].instance_len > 0) {
409
0
      vbranch->instance.len = _ksr_branches[i].instance_len;
410
0
      vbranch->instance.s = _ksr_branches[i].instance;
411
0
    }
412
0
    if(_ksr_branches[i].location_ua_len > 0) {
413
0
      vbranch->location_ua.len = _ksr_branches[i].location_ua_len;
414
0
      vbranch->location_ua.s = _ksr_branches[i].location_ua;
415
0
    }
416
0
    vbranch->otcpid = _ksr_branches[i].otcpid;
417
0
    return 1;
418
0
  } else {
419
0
    vbranch->q = Q_UNSPECIFIED;
420
0
    return 0;
421
0
  }
422
0
}
423
424
/**
425
 * Link branch attributes in the data structure and advance the iterator on
426
 * return of a valid branch
427
 * - return: -1 (<0) on error; 0 - on no valid branch; 1 - on a valid branch
428
 */
429
int next_branch_data(branch_data_t *vbranch)
430
0
{
431
0
  int ret;
432
0
  ret = get_branch_data(branch_iterator, vbranch);
433
0
  if(ret <= 0) {
434
0
    return ret;
435
0
  }
436
0
  branch_iterator++;
437
0
  return ret;
438
0
}
439
440
/*
441
 * Empty the dset array
442
 */
443
void clear_branches(void)
444
0
{
445
0
  nr_branches = 0;
446
0
  ruri_q = Q_UNSPECIFIED;
447
0
  ruri_bflags = 0;
448
0
  ruri_mark_consumed();
449
0
}
450
451
452
/**  Add a new branch to the current destination set.
453
 * @param msg sip message, used for getting the uri if not specified (0).
454
 * @param uri uri, can be 0 (in which case the uri is taken from msg)
455
 * @param dst_uri destination uri, can be 0.
456
 * @param path path vector (passed in a string), can be 0.
457
 * @param q  q value.
458
 * @param flags per branch flags.
459
 * @param force_socket socket that should be used when sending.
460
 * @param instance sip instance contact header param value
461
 * @param reg_id reg-id contact header param value
462
 * @param ruid ruid value from usrloc
463
 * @param location_ua location user agent
464
 *
465
 * @return  <0 (-1) on failure, 1 on success (script convention).
466
 */
467
int append_branch(struct sip_msg *msg, str *uri, str *dst_uri, str *path,
468
    qvalue_t q, unsigned int flags, struct socket_info *force_socket,
469
    str *instance, unsigned int reg_id, str *ruid, str *location_ua)
470
0
{
471
0
  str luri;
472
473
  /* if we have already set up the maximum number
474
   * of branches, don't try new ones
475
   */
476
0
  if(unlikely(nr_branches == sr_dst_max_branches - 1)) {
477
0
    LM_ERR("max nr of branches exceeded\n");
478
0
    ser_error = E_TOO_MANY_BRANCHES;
479
0
    return -1;
480
0
  }
481
482
  /* if not parameterized, take current uri */
483
0
  if(uri == 0 || uri->len == 0 || uri->s == 0) {
484
0
    if(msg == NULL) {
485
0
      LM_ERR("no new uri and no msg to take r-uri\n");
486
0
      ser_error = E_INVALID_PARAMS;
487
0
      return -1;
488
0
    }
489
0
    if(msg->new_uri.s)
490
0
      luri = msg->new_uri;
491
0
    else
492
0
      luri = msg->first_line.u.request.uri;
493
0
  } else {
494
0
    luri = *uri;
495
0
  }
496
497
0
  if(unlikely(luri.len > MAX_URI_SIZE - 1)) {
498
0
    LM_ERR("too long uri: %.*s\n", luri.len, luri.s);
499
0
    return -1;
500
0
  }
501
502
  /* copy the dst_uri */
503
0
  if(dst_uri && dst_uri->len && dst_uri->s) {
504
0
    if(unlikely(dst_uri->len > MAX_URI_SIZE - 1)) {
505
0
      LM_ERR("too long dst_uri: %.*s\n", dst_uri->len, dst_uri->s);
506
0
      return -1;
507
0
    }
508
0
    memcpy(_ksr_branches[nr_branches].dst_uri, dst_uri->s, dst_uri->len);
509
0
    _ksr_branches[nr_branches].dst_uri[dst_uri->len] = 0;
510
0
    _ksr_branches[nr_branches].dst_uri_len = dst_uri->len;
511
0
  } else {
512
0
    _ksr_branches[nr_branches].dst_uri[0] = '\0';
513
0
    _ksr_branches[nr_branches].dst_uri_len = 0;
514
0
  }
515
516
  /* copy the path string */
517
0
  if(unlikely(path && path->len && path->s)) {
518
0
    if(unlikely(path->len > MAX_PATH_SIZE - 1)) {
519
0
      LM_ERR("too long path: %.*s\n", path->len, path->s);
520
0
      return -1;
521
0
    }
522
0
    memcpy(_ksr_branches[nr_branches].path, path->s, path->len);
523
0
    _ksr_branches[nr_branches].path[path->len] = 0;
524
0
    _ksr_branches[nr_branches].path_len = path->len;
525
0
  } else {
526
0
    _ksr_branches[nr_branches].path[0] = '\0';
527
0
    _ksr_branches[nr_branches].path_len = 0;
528
0
  }
529
530
  /* copy the ruri */
531
0
  memcpy(_ksr_branches[nr_branches].uri, luri.s, luri.len);
532
0
  _ksr_branches[nr_branches].uri[luri.len] = 0;
533
0
  _ksr_branches[nr_branches].len = luri.len;
534
0
  _ksr_branches[nr_branches].q = q;
535
536
0
  _ksr_branches[nr_branches].force_send_socket = force_socket;
537
0
  _ksr_branches[nr_branches].flags = flags;
538
539
  /* copy instance string */
540
0
  if(unlikely(instance && instance->len && instance->s)) {
541
0
    if(unlikely(instance->len > MAX_INSTANCE_SIZE - 1)) {
542
0
      LM_ERR("too long instance: %.*s\n", instance->len, instance->s);
543
0
      return -1;
544
0
    }
545
0
    memcpy(_ksr_branches[nr_branches].instance, instance->s, instance->len);
546
0
    _ksr_branches[nr_branches].instance[instance->len] = 0;
547
0
    _ksr_branches[nr_branches].instance_len = instance->len;
548
0
  } else {
549
0
    _ksr_branches[nr_branches].instance[0] = '\0';
550
0
    _ksr_branches[nr_branches].instance_len = 0;
551
0
  }
552
553
  /* copy reg_id */
554
0
  _ksr_branches[nr_branches].reg_id = reg_id;
555
556
  /* copy ruid string */
557
0
  if(unlikely(ruid && ruid->len && ruid->s)) {
558
0
    if(unlikely(ruid->len > MAX_RUID_SIZE - 1)) {
559
0
      LM_ERR("too long ruid: %.*s\n", ruid->len, ruid->s);
560
0
      return -1;
561
0
    }
562
0
    memcpy(_ksr_branches[nr_branches].ruid, ruid->s, ruid->len);
563
0
    _ksr_branches[nr_branches].ruid[ruid->len] = 0;
564
0
    _ksr_branches[nr_branches].ruid_len = ruid->len;
565
0
  } else {
566
0
    _ksr_branches[nr_branches].ruid[0] = '\0';
567
0
    _ksr_branches[nr_branches].ruid_len = 0;
568
0
  }
569
570
0
  if(unlikely(location_ua && location_ua->len && location_ua->s)) {
571
0
    if(unlikely(location_ua->len > MAX_UA_SIZE)) {
572
0
      LM_ERR("too long location_ua: %.*s\n", location_ua->len,
573
0
          location_ua->s);
574
0
      return -1;
575
0
    }
576
0
    memcpy(_ksr_branches[nr_branches].location_ua, location_ua->s,
577
0
        location_ua->len);
578
0
    _ksr_branches[nr_branches].location_ua[location_ua->len] = 0;
579
0
    _ksr_branches[nr_branches].location_ua_len = location_ua->len;
580
0
  } else {
581
0
    _ksr_branches[nr_branches].location_ua[0] = '\0';
582
0
    _ksr_branches[nr_branches].location_ua_len = 0;
583
0
  }
584
585
0
  nr_branches++;
586
0
  return 1;
587
0
}
588
589
590
/**  Push a new branch to the current destination set.
591
 * @param msg sip message, used for getting the uri if not specified (0).
592
 * @param uri uri, can be 0 (in which case the uri is taken from msg)
593
 * @param dst_uri destination uri, can be 0.
594
 * @param path path vector (passed in a string), can be 0.
595
 * @param q  q value.
596
 * @param flags per branch flags.
597
 * @param force_socket socket that should be used when sending.
598
 * @param instance sip instance contact header param value
599
 * @param reg_id reg-id contact header param value
600
 * @param ruid ruid value from usrloc
601
 * @param location_ua location user agent
602
 *
603
 * @return NULL on failure, new branch pointer on success.
604
 */
605
branch_t *ksr_push_branch(struct sip_msg *msg, str *uri, str *dst_uri,
606
    str *path, qvalue_t q, unsigned int flags,
607
    struct socket_info *force_socket, str *instance, unsigned int reg_id,
608
    str *ruid, str *location_ua)
609
0
{
610
0
  if(append_branch(msg, uri, dst_uri, path, q, flags, force_socket, instance,
611
0
         reg_id, ruid, location_ua)
612
0
      < 0) {
613
0
    return NULL;
614
0
  }
615
0
  return &_ksr_branches[nr_branches - 1];
616
0
}
617
618
/*! \brief
619
 * Combines the given elements into a Contact header field
620
 * dest = target buffer, will be updated to new position after the printed contact
621
 * uri, q = contact elements
622
 * end = end of target buffer
623
 * Returns 0 on success or -1 on error (buffer is too short)
624
 */
625
static int print_contact_str(char **dest, str *uri, qvalue_t q, str *path,
626
    unsigned int flags, char *end, int options)
627
0
{
628
0
  char *p = *dest;
629
0
  str buf;
630
631
  /* uri */
632
0
  if(p + uri->len + 2 > end) {
633
0
    return -1;
634
0
  }
635
0
  *p++ = '<';
636
0
  memcpy(p, uri->s, uri->len);
637
0
  p += uri->len;
638
639
  /* uri parameters */
640
  /* path vector as route header parameter */
641
0
  if((options & DS_PATH) && path->len > 0) {
642
0
    if(p + ROUTE_PARAM_LEN + path->len > end) {
643
0
      return -1;
644
0
    }
645
0
    memcpy(p, ROUTE_PARAM, ROUTE_PARAM_LEN);
646
0
    p += ROUTE_PARAM_LEN;
647
    /* copy escaped path into dest */
648
0
    buf.s = p;
649
0
    buf.len = end - p;
650
0
    if(escape_param(path, &buf) < 0) {
651
0
      return -1;
652
0
    }
653
0
    p += buf.len;
654
0
  }
655
656
  /* end of uri parameters */
657
0
  *p++ = '>';
658
659
  /* header parameters */
660
  /* q value */
661
0
  if(q != Q_UNSPECIFIED) {
662
0
    buf.s = q2str(q, (unsigned int *)&buf.len);
663
0
    if(p + Q_PARAM_LEN + buf.len > end) {
664
0
      return -1;
665
0
    }
666
0
    memcpy(p, Q_PARAM, Q_PARAM_LEN);
667
0
    p += Q_PARAM_LEN;
668
0
    memcpy(p, buf.s, buf.len);
669
0
    p += buf.len;
670
0
  }
671
672
  /* branch flags (not SIP standard conformant) */
673
0
  if(options & DS_FLAGS) {
674
0
    buf.s = int2str(flags, &buf.len);
675
0
    if(p + FLAGS_PARAM_LEN + buf.len > end) {
676
0
      return -1;
677
0
    }
678
0
    memcpy(p, FLAGS_PARAM, FLAGS_PARAM_LEN);
679
0
    p += FLAGS_PARAM_LEN;
680
0
    memcpy(p, buf.s, buf.len);
681
0
    p += buf.len;
682
0
  }
683
684
0
  *dest = p;
685
0
  return 0;
686
0
}
687
688
689
/*
690
 * Create a Contact header field from the dset
691
 * array
692
 */
693
char *print_dset(struct sip_msg *msg, int *len, int options)
694
0
{
695
0
  int cnt = 0;
696
0
  qvalue_t q;
697
0
  str uri, path;
698
0
  unsigned int flags;
699
0
  char *p;
700
0
  int crt_branch;
701
0
  static char dset[MAX_REDIRECTION_LEN];
702
0
  char *end = dset + MAX_REDIRECTION_LEN;
703
704
  /* backup current branch index to restore it later */
705
0
  crt_branch = get_branch_iterator();
706
707
  /* contact header name */
708
0
  if(CONTACT_LEN + CRLF_LEN + 1 > MAX_REDIRECTION_LEN) {
709
0
    goto memfail;
710
0
  }
711
0
  memcpy(dset, CONTACT, CONTACT_LEN);
712
0
  p = dset + CONTACT_LEN;
713
714
  /* current uri */
715
0
  if(msg->new_uri.s) {
716
0
    if(print_contact_str(&p, &msg->new_uri, ruri_q, &msg->path_vec,
717
0
           ruri_bflags, end, options)
718
0
        < 0) {
719
0
      goto memfail;
720
0
    }
721
0
    cnt++;
722
0
  }
723
724
  /* branches */
725
0
  init_branch_iterator();
726
0
  while((uri.s = next_branch(&uri.len, &q, 0, &path, &flags, 0, 0, 0, 0))) {
727
0
    if(cnt > 0) {
728
0
      if(p + CONTACT_DELIM_LEN > end) {
729
0
        goto memfail;
730
0
      }
731
0
      memcpy(p, CONTACT_DELIM, CONTACT_DELIM_LEN);
732
0
      p += CONTACT_DELIM_LEN;
733
0
    }
734
735
0
    if(print_contact_str(&p, &uri, q, &path, flags, end, options) < 0) {
736
0
      goto memfail;
737
0
    }
738
739
0
    cnt++;
740
0
  }
741
742
0
  if(cnt == 0) {
743
0
    LM_INFO("no new r-uri or branches\n");
744
0
    goto notfound;
745
0
  }
746
747
0
  if(p + CRLF_LEN + 1 > end) {
748
0
    goto memfail;
749
0
  }
750
0
  memcpy(p, CRLF " ", CRLF_LEN + 1);
751
0
  *len = p - dset + CRLF_LEN;
752
0
  set_branch_iterator(crt_branch);
753
0
  return dset;
754
755
0
memfail:
756
0
  LM_ERR("redirection buffer length exceed\n");
757
0
notfound:
758
0
  *len = 0;
759
0
  set_branch_iterator(crt_branch);
760
0
  return 0;
761
0
}
762
763
764
/*
765
 * Sets the q parameter of the Request-URI
766
 */
767
void set_ruri_q(qvalue_t q)
768
0
{
769
0
  ruri_q = q;
770
0
}
771
772
773
/*
774
 * Return the q value of the Request-URI
775
 */
776
qvalue_t get_ruri_q(void)
777
0
{
778
0
  return ruri_q;
779
0
}
780
781
782
/*
783
 * Rewrite Request-URI
784
 */
785
int rewrite_uri(struct sip_msg *_m, str *_s)
786
0
{
787
0
  char *buf = NULL;
788
789
0
  if(_m->new_uri.s == NULL || _m->new_uri.len < _s->len) {
790
0
    buf = (char *)pkg_malloc(_s->len + 1);
791
0
    if(!buf) {
792
0
      PKG_MEM_ERROR;
793
0
      return -1;
794
0
    }
795
0
  }
796
0
  if(buf != NULL) {
797
0
    if(_m->new_uri.s)
798
0
      pkg_free(_m->new_uri.s);
799
0
  } else {
800
0
    buf = _m->new_uri.s;
801
0
  }
802
803
0
  memcpy(buf, _s->s, _s->len);
804
0
  buf[_s->len] = '\0';
805
806
0
  _m->parsed_uri_ok = 0;
807
808
0
  _m->new_uri.s = buf;
809
0
  _m->new_uri.len = _s->len;
810
  /* mark ruri as new and available for forking */
811
0
  ruri_mark_new();
812
813
0
  return 1;
814
0
}
815
816
/*
817
 * Reset Request-URI
818
 */
819
void reset_uri(sip_msg_t *msg)
820
0
{
821
0
  if(msg->new_uri.s == NULL) {
822
0
    return;
823
0
  }
824
0
  pkg_free(msg->new_uri.s);
825
0
  msg->new_uri.len = 0;
826
0
  msg->new_uri.s = 0;
827
0
  msg->parsed_uri_ok = 0;
828
0
  ruri_mark_new();
829
0
  return;
830
0
}
831
832
/**
833
 * return src ip, port and proto as a SIP uri or proxy address
834
 * - value stored in a static buffer
835
 * - mode=0 return uri, mode=1 return proxy address
836
 */
837
int msg_get_src_addr(sip_msg_t *msg, str *uri, int mode)
838
0
{
839
0
  static char buf[80];
840
0
  char *p;
841
0
  str ip, port;
842
0
  int len;
843
0
  str proto;
844
845
0
  if(msg == NULL || uri == NULL) {
846
0
    LM_ERR("invalid parameter value\n");
847
0
    return -1;
848
0
  }
849
850
0
  ip.s = ip_addr2a(&msg->rcv.src_ip);
851
0
  ip.len = strlen(ip.s);
852
853
0
  port.s = int2str(msg->rcv.src_port, &port.len);
854
855
0
  switch(msg->rcv.proto) {
856
0
    case PROTO_NONE:
857
0
    case PROTO_UDP:
858
0
      if(mode == 0) {
859
0
        proto.s =
860
0
            0; /* Do not add transport parameter, UDP is default */
861
0
        proto.len = 0;
862
0
      } else {
863
0
        proto.s = "udp";
864
0
        proto.len = 3;
865
0
      }
866
0
      break;
867
868
0
    case PROTO_TCP:
869
0
      proto.s = "tcp";
870
0
      proto.len = 3;
871
0
      break;
872
873
0
    case PROTO_TLS:
874
0
      proto.s = "tls";
875
0
      proto.len = 3;
876
0
      break;
877
878
0
    case PROTO_SCTP:
879
0
      proto.s = "sctp";
880
0
      proto.len = 4;
881
0
      break;
882
883
0
    case PROTO_WS:
884
0
    case PROTO_WSS:
885
0
      proto.s = "ws";
886
0
      proto.len = 2;
887
0
      break;
888
889
0
    default:
890
0
      LM_ERR("unknown transport protocol\n");
891
0
      return -1;
892
0
  }
893
894
0
  len = ip.len + 2 * (msg->rcv.src_ip.af == AF_INET6) + 1 + port.len;
895
0
  if(mode == 0) {
896
0
    len += 4;
897
0
    if(proto.s) {
898
0
      len += TRANSPORT_PARAM_LEN;
899
0
      len += proto.len;
900
0
    }
901
0
  } else {
902
0
    len += proto.len + 1;
903
0
  }
904
905
0
  if(len > 79) {
906
0
    LM_ERR("buffer too small\n");
907
0
    return -1;
908
0
  }
909
910
0
  p = buf;
911
0
  if(mode == 0) {
912
0
    memcpy(p, "sip:", 4);
913
0
    p += 4;
914
0
  } else {
915
0
    memcpy(p, proto.s, proto.len);
916
0
    p += proto.len;
917
0
    *p++ = ':';
918
0
  }
919
920
0
  if(msg->rcv.src_ip.af == AF_INET6)
921
0
    *p++ = '[';
922
0
  memcpy(p, ip.s, ip.len);
923
0
  p += ip.len;
924
0
  if(msg->rcv.src_ip.af == AF_INET6)
925
0
    *p++ = ']';
926
927
0
  *p++ = ':';
928
929
0
  memcpy(p, port.s, port.len);
930
0
  p += port.len;
931
932
0
  if(mode == 0 && proto.s) {
933
0
    memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
934
0
    p += TRANSPORT_PARAM_LEN;
935
936
0
    memcpy(p, proto.s, proto.len);
937
0
  }
938
939
0
  uri->s = buf;
940
0
  uri->len = len;
941
0
  uri->s[uri->len] = '\0';
942
943
0
  return 0;
944
0
}
945
946
947
/**
948
 * set name of alias parameter used for contact/r-uri src/rcv address encoding
949
 */
950
int ksr_contact_alias_set_name(str *aname)
951
0
{
952
0
  _ksr_contact_salias.s = (char *)pkg_malloc(aname->len + 3);
953
0
  if(_ksr_contact_salias.s == NULL) {
954
0
    PKG_MEM_ERROR;
955
0
    return -1;
956
0
  }
957
0
  _ksr_contact_salias.s[0] = ';';
958
0
  memcpy(_ksr_contact_salias.s + 1, aname->s, aname->len);
959
0
  _ksr_contact_salias.s[aname->len + 1] = '=';
960
0
  _ksr_contact_salias.s[aname->len + 2] = '\0';
961
0
  _ksr_contact_salias.len = aname->len + 2;
962
0
  _ksr_contact_alias.s = _ksr_contact_salias.s + 1;
963
0
  _ksr_contact_alias.len = _ksr_contact_salias.len - 1;
964
0
  LM_DBG("new contact alias parameter expression [%.*s]\n",
965
0
      _ksr_contact_salias.len, _ksr_contact_salias.s);
966
967
0
  return 0;
968
0
}
969
970
/**
971
 * add alias parameter with encoding of source address
972
 * - nuri->s must point to a buffer of nuri->len size
973
 */
974
int uri_add_rcv_alias(sip_msg_t *msg, str *uri, str *nuri)
975
0
{
976
0
  char *p;
977
0
  str ip, port;
978
0
  int len;
979
980
0
  if(msg == NULL || uri == NULL || nuri == NULL) {
981
0
    LM_ERR("invalid parameter value\n");
982
0
    return -1;
983
0
  }
984
985
0
  ip.s = ip_addr2a(&msg->rcv.src_ip);
986
0
  ip.len = strlen(ip.s);
987
988
0
  port.s = int2str(msg->rcv.src_port, &port.len);
989
990
  /*uri;alias=[ip]~port~proto*/
991
0
  len = uri->len + _ksr_contact_salias.len + ip.len + port.len + 6;
992
0
  if(len >= nuri->len) {
993
0
    LM_ERR("not enough space - new uri len: %d (buf size: %d)\n", len,
994
0
        nuri->len);
995
0
    return -1;
996
0
  }
997
0
  p = nuri->s;
998
0
  memcpy(p, uri->s, uri->len);
999
0
  p += uri->len;
1000
0
  memcpy(p, _ksr_contact_salias.s, _ksr_contact_salias.len);
1001
0
  p += _ksr_contact_salias.len;
1002
0
  if(msg->rcv.src_ip.af == AF_INET6)
1003
0
    *p++ = '[';
1004
0
  memcpy(p, ip.s, ip.len);
1005
0
  p += ip.len;
1006
0
  if(msg->rcv.src_ip.af == AF_INET6)
1007
0
    *p++ = ']';
1008
0
  *p++ = '~';
1009
0
  memcpy(p, port.s, port.len);
1010
0
  p += port.len;
1011
0
  *p++ = '~';
1012
0
  *p++ = msg->rcv.proto + '0';
1013
0
  nuri->len = p - nuri->s;
1014
0
  nuri->s[nuri->len] = '\0';
1015
1016
0
  LM_DBG("encoded <%.*s> => [%.*s]\n", uri->len, uri->s, nuri->len, nuri->s);
1017
0
  return 0;
1018
0
}
1019
1020
/**
1021
 * restore from alias parameter with encoding of source address
1022
 * - nuri->s must point to a buffer of nuri->len size
1023
 * - suri->s must point to a buffer of suri->len size
1024
 */
1025
int uri_restore_rcv_alias(str *uri, str *nuri, str *suri)
1026
0
{
1027
0
  char *p;
1028
0
  str skip;
1029
0
  str ip, port, sproto;
1030
0
  int proto;
1031
1032
0
  if(uri == NULL || nuri == NULL || suri == NULL) {
1033
0
    LM_ERR("invalid parameter value\n");
1034
0
    return -1;
1035
0
  }
1036
1037
  /* sip:x;alias=1.1.1.1~0~0 */
1038
0
  if(uri->len < _ksr_contact_salias.len + 16) {
1039
    /* no alias possible */
1040
0
    return -2;
1041
0
  }
1042
0
  p = uri->s + uri->len - _ksr_contact_salias.len - 11;
1043
0
  skip.s = 0;
1044
0
  while(p > uri->s + 5) {
1045
0
    if(strncmp(p, _ksr_contact_salias.s, _ksr_contact_salias.len) == 0) {
1046
0
      skip.s = p;
1047
0
      break;
1048
0
    }
1049
0
    p--;
1050
0
  }
1051
0
  if(skip.s == 0) {
1052
    /* alias parameter not found */
1053
0
    return -2;
1054
0
  }
1055
0
  p += _ksr_contact_salias.len;
1056
0
  ip.s = p;
1057
0
  p = (char *)memchr(ip.s, '~', (size_t)(uri->s + uri->len - ip.s));
1058
0
  if(p == NULL) {
1059
    /* proper alias parameter not found */
1060
0
    return -2;
1061
0
  }
1062
0
  ip.len = p - ip.s;
1063
0
  p++;
1064
0
  if(p >= uri->s + uri->len) {
1065
    /* proper alias parameter not found */
1066
0
    return -2;
1067
0
  }
1068
0
  port.s = p;
1069
0
  p = (char *)memchr(port.s, '~', (size_t)(uri->s + uri->len - port.s));
1070
0
  if(p == NULL) {
1071
    /* proper alias parameter not found */
1072
0
    return -2;
1073
0
  }
1074
0
  port.len = p - port.s;
1075
0
  p++;
1076
0
  if(p >= uri->s + uri->len) {
1077
    /* proper alias parameter not found */
1078
0
    return -2;
1079
0
  }
1080
0
  proto = (int)(*p - '0');
1081
0
  p++;
1082
1083
0
  if(p != uri->s + uri->len && *p != ';') {
1084
    /* proper alias parameter not found */
1085
0
    return -2;
1086
0
  }
1087
0
  skip.len = (int)(p - skip.s);
1088
1089
0
  if(suri->len <= 4 + ip.len + 1 + port.len + 11 /*;transport=*/ + 4) {
1090
0
    LM_ERR("address buffer too small\n");
1091
0
    return -1;
1092
0
  }
1093
0
  if(nuri->len <= uri->len - skip.len) {
1094
0
    LM_ERR("uri buffer too small\n");
1095
0
    return -1;
1096
0
  }
1097
1098
0
  p = nuri->s;
1099
0
  memcpy(p, uri->s, (size_t)(skip.s - uri->s));
1100
0
  p += skip.s - uri->s;
1101
0
  memcpy(p, skip.s + skip.len,
1102
0
      (size_t)(uri->s + uri->len - skip.s - skip.len));
1103
0
  p += uri->s + uri->len - skip.s - skip.len;
1104
0
  nuri->len = p - nuri->s;
1105
1106
0
  p = suri->s;
1107
0
  memcpy(p, "sip:", 4);
1108
0
  p += 4;
1109
0
  memcpy(p, ip.s, ip.len);
1110
0
  p += ip.len;
1111
0
  *p++ = ':';
1112
0
  memcpy(p, port.s, port.len);
1113
0
  p += port.len;
1114
0
  proto_type_to_str((unsigned short)proto, &sproto);
1115
0
  if(sproto.len > 0 && proto != PROTO_UDP) {
1116
0
    memcpy(p, ";transport=", 11);
1117
0
    p += 11;
1118
0
    memcpy(p, sproto.s, sproto.len);
1119
0
    p += sproto.len;
1120
0
  }
1121
0
  suri->len = p - suri->s;
1122
1123
0
  LM_DBG("decoded <%.*s> => [%.*s] [%.*s]\n", uri->len, uri->s, nuri->len,
1124
0
      nuri->s, suri->len, suri->s);
1125
1126
0
  return 0;
1127
0
}
1128
1129
1130
/**
1131
 * trim alias parameter from uri
1132
 * - nuri->s must point to a buffer of nuri->len size
1133
 */
1134
int uri_trim_rcv_alias(str *uri, str *nuri)
1135
0
{
1136
0
  char *p;
1137
0
  str skip;
1138
0
  str ip, port;
1139
1140
0
  if(uri == NULL || nuri == NULL) {
1141
0
    LM_ERR("invalid parameter value\n");
1142
0
    return -1;
1143
0
  }
1144
1145
  /* sip:x;alias=1.1.1.1~0~0 */
1146
0
  if(uri->len < _ksr_contact_salias.len + 16) {
1147
    /* no alias possible */
1148
0
    return 0;
1149
0
  }
1150
0
  p = uri->s + uri->len - _ksr_contact_salias.len - 11;
1151
0
  skip.s = 0;
1152
0
  while(p > uri->s + 5) {
1153
0
    if(strncmp(p, _ksr_contact_salias.s, _ksr_contact_salias.len) == 0) {
1154
0
      skip.s = p;
1155
0
      break;
1156
0
    }
1157
0
    p--;
1158
0
  }
1159
0
  if(skip.s == 0) {
1160
    /* alias parameter not found */
1161
0
    return 0;
1162
0
  }
1163
0
  p += _ksr_contact_salias.len;
1164
0
  ip.s = p;
1165
0
  p = (char *)memchr(ip.s, '~', (size_t)(uri->s + uri->len - ip.s));
1166
0
  if(p == NULL) {
1167
    /* proper alias parameter not found */
1168
0
    return 0;
1169
0
  }
1170
0
  ip.len = p - ip.s;
1171
0
  p++;
1172
0
  if(p >= uri->s + uri->len) {
1173
    /* proper alias parameter not found */
1174
0
    return 0;
1175
0
  }
1176
0
  port.s = p;
1177
0
  p = (char *)memchr(port.s, '~', (size_t)(uri->s + uri->len - port.s));
1178
0
  if(p == NULL) {
1179
    /* proper alias parameter not found */
1180
0
    return 0;
1181
0
  }
1182
0
  port.len = p - port.s;
1183
0
  p++;
1184
0
  if(p >= uri->s + uri->len) {
1185
    /* proper alias parameter not found */
1186
0
    return 0;
1187
0
  }
1188
  /* jump over proto */
1189
0
  p++;
1190
1191
0
  if(p != uri->s + uri->len && *p != ';') {
1192
    /* proper alias parameter not found */
1193
0
    return 0;
1194
0
  }
1195
0
  skip.len = (int)(p - skip.s);
1196
0
  if(nuri->len <= uri->len - skip.len) {
1197
0
    LM_ERR("uri buffer too small\n");
1198
0
    return -1;
1199
0
  }
1200
1201
0
  p = nuri->s;
1202
0
  memcpy(p, uri->s, (size_t)(skip.s - uri->s));
1203
0
  p += skip.s - uri->s;
1204
0
  memcpy(p, skip.s + skip.len,
1205
0
      (size_t)(uri->s + uri->len - skip.s - skip.len));
1206
0
  p += uri->s + uri->len - skip.s - skip.len;
1207
0
  nuri->len = p - nuri->s;
1208
1209
0
  LM_DBG("decoded <%.*s> => [%.*s]\n", uri->len, uri->s, nuri->len, nuri->s);
1210
0
  return 1;
1211
0
}
1212
1213
/**
1214
 * encode sip uri to uri alias parameter format
1215
 * - param: iuri - input sip uri
1216
 * - param: ualias - output uri alias value in format: address~port~proto
1217
 *   * ualias->s must point to a buffer of size ualias->len, at least iuri->len
1218
 *   * ualias->len is adjusted to the output value length
1219
 * - return 0 on success, negative on error
1220
 */
1221
int ksr_uri_alias_encode(str *iuri, str *ualias)
1222
0
{
1223
0
  sip_uri_t puri;
1224
0
  char *p;
1225
1226
0
  if(parse_uri(iuri->s, iuri->len, &puri) < 0) {
1227
0
    LM_ERR("failed to parse uri [%.*s]\n", iuri->len, iuri->s);
1228
0
    return -1;
1229
0
  }
1230
1231
  /*host~port~proto*/
1232
0
  if(puri.host.len + 16 >= ualias->len) {
1233
0
    LM_ERR("not enough space to build uri alias - buf size: %d\n",
1234
0
        ualias->len);
1235
0
    return -1;
1236
0
  }
1237
0
  p = ualias->s;
1238
0
  memcpy(p, puri.host.s, puri.host.len);
1239
0
  p += puri.host.len;
1240
0
  *p++ = '~';
1241
0
  if(puri.port.len > 0) {
1242
0
    memcpy(p, puri.port.s, puri.port.len);
1243
0
    p += puri.port.len;
1244
0
  } else {
1245
0
    if(puri.proto == PROTO_TLS || puri.proto == PROTO_WSS) {
1246
0
      memcpy(p, "5061", 4);
1247
0
    } else {
1248
0
      memcpy(p, "5060", 4);
1249
0
    }
1250
0
    p += 4;
1251
0
  }
1252
0
  *p++ = '~';
1253
0
  *p++ = ((puri.proto) ? puri.proto : 1) + '0';
1254
0
  ualias->len = p - ualias->s;
1255
0
  ualias->s[ualias->len] = '\0';
1256
1257
0
  LM_DBG("encoded <%.*s> => [%.*s]\n", iuri->len, iuri->s, ualias->len,
1258
0
      ualias->s);
1259
1260
0
  return 0;
1261
0
}
1262
1263
/**
1264
 * decode uri alias parameter to a sip uri
1265
 * - param: ualias - uri alias value in format: address~port~proto
1266
 * - param: ouri - output uri - ouri->s must point to a buffer of size ouri->len
1267
 *   * ouri->len is adjusted to the output value length
1268
 * - return 0 on success, negative on error
1269
 */
1270
int ksr_uri_alias_decode(str *ualias, str *ouri)
1271
0
{
1272
0
  int n;
1273
0
  char *p;
1274
0
  int nproto;
1275
0
  str sproto;
1276
1277
  /* 24 => sip:...;transport=sctp */
1278
0
  if(ualias->len + 24 >= ouri->len) {
1279
0
    LM_ERR("received uri alias is too long: %d\n", ualias->len);
1280
0
    return -1;
1281
0
  }
1282
1283
  /* received=ip~port~proto */
1284
0
  memcpy(ouri->s, "sip:", 4);
1285
0
  memcpy(ouri->s + 4, ualias->s, ualias->len);
1286
0
  ouri->s[4 + ualias->len] = '\0';
1287
0
  p = ouri->s + 4;
1288
0
  n = 0;
1289
0
  while(*p != '\0') {
1290
0
    if(*p == '~') {
1291
0
      n++;
1292
0
      if(n == 1) {
1293
        /* port */
1294
0
        *p = ':';
1295
0
      } else if(n == 2) {
1296
        /* proto */
1297
0
        *p = ';';
1298
0
        p++;
1299
0
        if(*p == '\0') {
1300
0
          LM_ERR("invalid received format\n");
1301
0
          goto error;
1302
0
        }
1303
0
        nproto = *p - '0';
1304
0
        if(nproto == PROTO_NONE) {
1305
0
          nproto = PROTO_UDP;
1306
0
        }
1307
0
        if(nproto != PROTO_UDP) {
1308
0
          proto_type_to_str(nproto, &sproto);
1309
0
          if(sproto.len == 0) {
1310
0
            LM_ERR("unknown proto in received param\n");
1311
0
            goto error;
1312
0
          }
1313
0
          memcpy(p, "transport=", 10);
1314
0
          p += 10;
1315
0
          memcpy(p, sproto.s, sproto.len);
1316
0
          p += sproto.len;
1317
0
        } else {
1318
          /* go back one byte to overwrite ';' */
1319
0
          p--;
1320
0
        }
1321
0
        ouri->len = (int)(p - ouri->s);
1322
0
        ouri->s[ouri->len] = '\0';
1323
0
        break;
1324
0
      } else {
1325
0
        LM_ERR("invalid number of separators (%d)\n", n);
1326
0
        goto error;
1327
0
      }
1328
0
    }
1329
0
    p++;
1330
0
  }
1331
0
  return 0;
1332
1333
0
error:
1334
0
  return -1;
1335
0
}
1336
1337
/**
1338
 * remove param from ouri, storing in nuri
1339
 * - nuri->len has to be set to the size of nuri->s buffer
1340
 */
1341
int ksr_uri_remove_param(str *ouri, str *pname, str *nuri)
1342
0
{
1343
0
  str t;
1344
0
  str pstart;
1345
0
  sip_uri_t puri;
1346
0
  param_hooks_t hooks;
1347
0
  param_t *params, *pit;
1348
1349
0
  if(nuri->len < ouri->len + 1) {
1350
0
    LM_ERR("output buffer too small (%d / %d)\n", nuri->len, ouri->len);
1351
0
    return -1;
1352
0
  }
1353
0
  if(parse_uri(ouri->s, ouri->len, &puri) < 0) {
1354
0
    LM_ERR("failed to parse uri [%.*s]\n", ouri->len, ouri->s);
1355
0
    return -1;
1356
0
  }
1357
0
  if(puri.sip_params.len > 0) {
1358
0
    t = puri.sip_params;
1359
0
  } else if(puri.params.len > 0) {
1360
0
    t = puri.params;
1361
0
  } else {
1362
0
    LM_DBG("no uri params [%.*s]\n", ouri->len, ouri->s);
1363
0
    memcpy(nuri->s, ouri->s, ouri->len);
1364
0
    nuri->len = ouri->len;
1365
0
    nuri->s[nuri->len] = 0;
1366
0
    return 0;
1367
0
  }
1368
1369
0
  if(parse_params(&t, CLASS_ANY, &hooks, &params) < 0) {
1370
0
    LM_ERR("ruri parameter parsing failed\n");
1371
0
    return -1;
1372
0
  }
1373
1374
0
  for(pit = params; pit; pit = pit->next) {
1375
0
    if((pit->name.len == pname->len)
1376
0
        && (strncasecmp(pit->name.s, pname->s, pname->len) == 0)) {
1377
0
      break;
1378
0
    }
1379
0
  }
1380
0
  if(pit == NULL) {
1381
0
    LM_DBG("uri param [%.*s] not found\n", pname->len, pname->s);
1382
0
    free_params(params);
1383
0
    memcpy(nuri->s, ouri->s, ouri->len);
1384
0
    nuri->len = ouri->len;
1385
0
    nuri->s[nuri->len] = 0;
1386
0
    return 0;
1387
0
  }
1388
1389
0
  pstart.s = pit->name.s;
1390
0
  while(pstart.s > ouri->s && *pstart.s != ';') {
1391
0
    pstart.s--;
1392
0
  }
1393
0
  memcpy(nuri->s, ouri->s, pstart.s - ouri->s);
1394
0
  nuri->len = pstart.s - ouri->s;
1395
1396
0
  if(pit->body.len > 0) {
1397
0
    if(pit->body.s + pit->body.len < ouri->s + ouri->len) {
1398
0
      memcpy(nuri->s + nuri->len, pit->body.s + pit->body.len,
1399
0
          ouri->s + ouri->len - pit->body.s - pit->body.len);
1400
0
      nuri->len += ouri->s + ouri->len - pit->body.s - pit->body.len;
1401
0
    }
1402
0
  } else {
1403
0
    if(pit->name.s + pit->name.len < ouri->s + ouri->len) {
1404
0
      memcpy(nuri->s + nuri->len, pit->name.s + pit->name.len,
1405
0
          ouri->s + ouri->len - pit->name.s - pit->name.len);
1406
0
      nuri->len += ouri->s + ouri->len - pit->name.s - pit->name.len;
1407
0
    }
1408
0
  }
1409
0
  nuri->s[nuri->len] = 0;
1410
1411
0
  free_params(params);
1412
1413
0
  return 0;
1414
0
}
1415
1416
/* address of record (aor) management */
1417
1418
/* address of record considered case sensitive
1419
 * - 0 = no; 1 = yes */
1420
static int aor_case_sensitive = 0;
1421
1422
int set_aor_case_sensitive(int mode)
1423
0
{
1424
0
  int r;
1425
0
  r = aor_case_sensitive;
1426
0
  aor_case_sensitive = mode;
1427
0
  return r;
1428
0
}
1429
1430
int get_aor_case_sensitive(void)
1431
0
{
1432
0
  return aor_case_sensitive;
1433
0
}