Coverage Report

Created: 2024-02-25 06:34

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