Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/msg_translator.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2001-2003 FhG Fokus
3
 *
4
 * This file is part of Kamailio, a free SIP server.
5
 *
6
 * Kamailio is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version
10
 *
11
 * Kamailio is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 *
20
 *
21
 *
22
 */
23
/** Via special params:
24
 * requests:
25
 * - if the address in via is different from the src_ip or an existing
26
 *   received=something is found, received=src_ip is added (and any preexisting
27
 *   received is deleted). received is added as the first via parameter if no
28
 *   receive is previously present or over the old receive.
29
 * - if the original via contains rport / rport=something or msg->msg_flags
30
 *   FL_FORCE_RPORT is set (e.g. script force_rport() cmd) rport=src_port
31
 *   is added (over previous rport / as first via param or after received
32
 *   if no received was present and received is added too)
33
 * local replies:
34
 *    (see also sl_send_reply)
35
 *  - rport and received are added in mostly the same way as for requests, but
36
 *    in the reverse order (first rport and then received). See also
37
 *    limitations.
38
 *  - if reply_to_via is set (default off) the local reply will be sent to
39
 *    the address in via (received is ignored since it was not set by us). The
40
 *    destination port is either the message source port if via contains rport
41
 *    or the FL_FORCE_RPORT flag is set or the port from the via. If either
42
 *    port or rport are present a normal dns lookup (instead of a srv lookup)
43
 *    is performed on the address. If no port is present and a srv lookup is
44
 *    performed the port is taken from the srv lookup. If the srv lookup failed
45
 *    or it was not performed, the port is set to the default sip port (5060).
46
 *  - if reply_to_via is off (default) the local reply is sent to the message
47
 *    source ip address. The destination port is set to the source port if
48
 *    rport is present or FL_FORCE_RPORT flag is set, to the via port or to
49
 *    the default sip port (5060) if neither rport or via port are present.
50
 * "normal" replies:
51
 *  - if received is present the message is sent to the received address else
52
 *    if no port is present (neither a normal via port or rport) a dns srv
53
 *    lookup is performed on the host part and the reply is sent to the
54
 *    resulting ip. If a port is present or the host part is an ip address
55
 *    the dns lookup will be a "normal" one (A or AAAA).
56
 *  - if rport is present, its value will be used as the destination port
57
 *   (and this will also disable srv lookups)
58
 *  - if no port is present the destination port will be taken from the srv
59
 *    lookup. If the srv lookup fails or is not performed (e.g. ip address
60
 *    in host) the destination port will be set to the default sip port (5060).
61
 *
62
 * Known limitations:
63
 * - when locally replying to a message, rport and received will be appended to
64
 *   the via header parameters (for forwarded requests they are inserted at the
65
 *   beginning).
66
 * - a locally generated reply might get two received via parameters if a
67
 *   received is already present in the original message (this should not
68
 *   happen though, but ...)
69
 *
70
 *--andrei
71
*/
72
73
/*!
74
 * \file
75
 * \brief Kamailio core :: Message translations
76
 * \ingroup core
77
 * Module: \ref core
78
 */
79
80
#include <sys/types.h>
81
#include <sys/socket.h>
82
#include <netdb.h>
83
#include <string.h>
84
#include <stdio.h>
85
#include <stdlib.h>
86
87
#include "comp_defs.h"
88
#include "msg_translator.h"
89
#include "globals.h"
90
#include "error.h"
91
#include "mem/mem.h"
92
#include "dprint.h"
93
#include "config.h"
94
#include "data_lump.h"
95
#include "data_lump_rpl.h"
96
#include "ip_addr.h"
97
#include "resolve.h"
98
#include "ut.h"
99
#include "pt.h"
100
#include "cfg/cfg.h"
101
#include "parser/parse_to.h"
102
#include "parser/parse_param.h"
103
#include "forward.h"
104
#include "str_list.h"
105
#include "pvapi.h"
106
#include "xavp.h"
107
#include "rand/kam_rand.h"
108
109
#define append_str_trans(_dest, _src, _len, _msg) \
110
0
  append_str((_dest), (_src), (_len));
111
112
extern char version[];
113
extern int version_len;
114
115
str _ksr_xavp_via_params = STR_NULL;
116
str _ksr_xavp_via_fields = STR_NULL;
117
str _ksr_xavp_via_reply_params = STR_NULL;
118
int ksr_local_rport = 0;
119
120
/** per process fixup function for global_req_flags.
121
  * It should be called from the configuration framework.
122
  */
123
void fix_global_req_flags(str *gname, str *name)
124
0
{
125
0
  global_req_flags = 0;
126
0
  switch(cfg_get(core, core_cfg, udp_mtu_try_proto)) {
127
0
    case PROTO_NONE:
128
0
    case PROTO_UDP:
129
      /* do nothing */
130
0
      break;
131
0
    case PROTO_TCP:
132
0
      global_req_flags |= FL_MTU_TCP_FB;
133
0
      break;
134
0
    case PROTO_TLS:
135
0
      global_req_flags |= FL_MTU_TLS_FB;
136
0
      break;
137
0
    case PROTO_SCTP:
138
0
      global_req_flags |= FL_MTU_SCTP_FB;
139
0
      break;
140
0
  }
141
0
  if(cfg_get(core, core_cfg, force_rport))
142
0
    global_req_flags |= FL_FORCE_RPORT;
143
0
}
144
145
146
/* checks if ip is in host(name) and ?host(ip)=name?
147
 * ip must be in network byte order!
148
 *  resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made
149
 * return 0 if equal */
150
static int check_via_address(
151
    struct ip_addr *ip, str *name, unsigned short port, int resolver)
152
0
{
153
0
  struct hostent *he;
154
0
  int i;
155
0
  char *s;
156
0
  int len;
157
0
  char lproto;
158
159
  /* maybe we are lucky and name it's an ip */
160
0
  s = ip_addr2a(ip);
161
0
  if(s) {
162
0
    LM_DBG("(%s, %.*s, %d)\n", s, name->len, name->s, resolver);
163
164
0
    len = strlen(s);
165
166
    /* check if name->s is an ipv6 address or an ipv6 address ref. */
167
0
    if((ip->af == AF_INET6)
168
0
        && (((len == name->len)
169
0
              && (strncasecmp(name->s, s, name->len) == 0))
170
0
            || ((len == (name->len - 2)) && (name->s[0] == '[')
171
0
                && (name->s[name->len - 1] == ']')
172
0
                && (strncasecmp(name->s + 1, s, len) == 0)))) {
173
0
      return 0;
174
0
    } else {
175
0
      if(unlikely(name->s == NULL)) {
176
0
        LM_CRIT("invalid Via host name\n");
177
0
        return -1;
178
0
      }
179
0
      if(len == name->len && (strncmp(name->s, s, name->len) == 0))
180
0
        return 0;
181
0
    }
182
0
  } else {
183
0
    LM_CRIT("could not convert ip address\n");
184
0
    return -1;
185
0
  }
186
187
0
  if(port == 0)
188
0
    port = SIP_PORT;
189
0
  if(resolver & DO_DNS) {
190
0
    LM_DBG("doing dns lookup\n");
191
    /* try all names ips */
192
0
    lproto = PROTO_NONE;
193
0
    he = sip_resolvehost(name, &port, &lproto); /* don't use naptr */
194
0
    if(he && ip->af == he->h_addrtype) {
195
0
      for(i = 0; he && he->h_addr_list[i]; i++) {
196
0
        if(memcmp(&he->h_addr_list[i], ip->u.addr, ip->len) == 0)
197
0
          return 0;
198
0
      }
199
0
    }
200
0
  }
201
0
  if(resolver & DO_REV_DNS) {
202
0
    LM_DBG("doing rev. dns lookup\n");
203
    /* try reverse dns */
204
0
    he = rev_resolvehost(ip);
205
0
    if(he && (strncmp(he->h_name, name->s, name->len) == 0))
206
0
      return 0;
207
0
    for(i = 0; he && he->h_aliases[i]; i++) {
208
0
      if(strncmp(he->h_aliases[i], name->s, name->len) == 0)
209
0
        return 0;
210
0
    }
211
0
  }
212
0
  return -1;
213
0
}
214
215
216
/* check if IP address in Via != source IP address of signaling,
217
 * or the sender requires adding rport or received values */
218
int received_test(struct sip_msg *msg)
219
0
{
220
0
  int rcvd;
221
222
0
  rcvd = msg->via1->received || msg->via1->rport
223
0
       || check_via_address(&msg->rcv.src_ip, &msg->via1->host,
224
0
           msg->via1->port, received_dns);
225
0
  return rcvd;
226
0
}
227
228
/* check if IP address in Via != source IP address of signaling */
229
int received_via_test(struct sip_msg *msg)
230
0
{
231
0
  int rcvd;
232
233
0
  rcvd = (check_via_address(&msg->rcv.src_ip, &msg->via1->host,
234
0
          msg->via1->port, received_dns)
235
0
      != 0);
236
0
  return rcvd;
237
0
}
238
239
static char *warning_builder(struct sip_msg *msg, unsigned int *returned_len)
240
0
{
241
0
  static char buf[MAX_WARNING_LEN];
242
0
  str *foo;
243
0
  int print_len, l;
244
0
  int clen;
245
0
  char *t;
246
247
0
#define str_print(string, string_len)    \
248
0
  do {                                 \
249
0
    l = (string_len);                \
250
0
    if((clen + l) > MAX_WARNING_LEN) \
251
0
      goto error_overflow;         \
252
0
    memcpy(buf + clen, (string), l); \
253
0
    clen += l;                       \
254
0
  } while(0)
255
256
0
#define str_lenpair_print(string, string_len, string2, string2_len) \
257
0
  do {                                                            \
258
0
    str_print(string, string_len);                              \
259
0
    str_print(string2, string2_len);                            \
260
0
  } while(0)
261
262
0
#define str_pair_print(string, string2, string2_len) \
263
0
  str_lenpair_print((string), strlen((string)), (string2), (string2_len))
264
265
0
#define str_int_print(string, intval)         \
266
0
  do {                                      \
267
0
    t = int2str((intval), &print_len);    \
268
0
    str_pair_print(string, t, print_len); \
269
0
  } while(0)
270
271
0
#define str_su_print(sockaddr)                 \
272
0
  do {                                       \
273
0
    t = su2a(&sockaddr, sizeof(sockaddr)); \
274
0
    print_len = strlen(t);                 \
275
0
    str_print(t, print_len);               \
276
0
  } while(0)
277
278
0
#define str_ipaddr_print(string, ipaddr_val)  \
279
0
  do {                                      \
280
0
    t = ip_addr2a((ipaddr_val));          \
281
0
    print_len = strlen(t);                \
282
0
    str_pair_print(string, t, print_len); \
283
0
  } while(0)
284
285
0
  clen = 0;
286
0
  str_print(WARNING, WARNING_LEN);
287
0
  str_su_print(msg->rcv.bind_address->su);
288
0
  str_print(WARNING_PHRASE, WARNING_PHRASE_LEN);
289
290
  /*adding out_uri*/
291
0
  if(msg->new_uri.s)
292
0
    foo = &(msg->new_uri);
293
0
  else
294
0
    foo = &(msg->first_line.u.request.uri);
295
  /* pid= */
296
0
  str_int_print(" pid=", my_pid());
297
  /* req_src_ip= */
298
0
  str_ipaddr_print(" req_src_ip=", &msg->rcv.src_ip);
299
0
  str_int_print(" req_src_port=", msg->rcv.src_port);
300
0
  str_pair_print(" in_uri=", msg->first_line.u.request.uri.s,
301
0
      msg->first_line.u.request.uri.len);
302
0
  str_pair_print(" out_uri=", foo->s, foo->len);
303
0
  str_pair_print(" via_cnt",
304
0
      (msg->parsed_flag & HDR_EOH_F) == HDR_EOH_F ? "=" : ">", 1);
305
0
  str_int_print("=", via_cnt);
306
0
  if(clen < MAX_WARNING_LEN) {
307
0
    buf[clen] = '"';
308
0
    clen++;
309
0
  } else
310
0
    goto error_overflow;
311
312
313
0
  *returned_len = clen;
314
0
  return buf;
315
0
error_overflow:
316
0
  LM_NOTICE("buffer size exceeded (probably too long URI)\n");
317
0
  *returned_len = 0;
318
0
  return 0;
319
0
}
320
321
322
char *received_builder(struct sip_msg *msg, unsigned int *received_len)
323
0
{
324
0
  char *buf;
325
0
  int len;
326
0
  struct ip_addr *source_ip;
327
0
  char *tmp;
328
0
  int tmp_len;
329
330
0
  source_ip = &msg->rcv.src_ip;
331
332
0
  buf = pkg_malloc(sizeof(char) * MAX_RECEIVED_SIZE);
333
0
  if(buf == 0) {
334
0
    ser_error = E_OUT_OF_MEM;
335
0
    PKG_MEM_ERROR;
336
0
    return 0;
337
0
  }
338
0
  memcpy(buf, RECEIVED, RECEIVED_LEN);
339
0
  if((tmp = ip_addr2a(source_ip)) == 0) {
340
0
    pkg_free(buf);
341
0
    return 0; /* error*/
342
0
  }
343
0
  tmp_len = strlen(tmp);
344
0
  len = RECEIVED_LEN + tmp_len;
345
346
0
  memcpy(buf + RECEIVED_LEN, tmp, tmp_len);
347
0
  buf[len] = 0; /*null terminate it */
348
349
0
  *received_len = len;
350
0
  return buf;
351
0
}
352
353
354
char *rport_builder(struct sip_msg *msg, unsigned int *rport_len)
355
0
{
356
0
  char *buf;
357
0
  char *tmp;
358
0
  int tmp_len;
359
0
  int len;
360
361
0
  tmp_len = 0;
362
0
  tmp = int2str(msg->rcv.src_port, &tmp_len);
363
0
  len = RPORT_LEN + tmp_len;
364
0
  buf = pkg_malloc(sizeof(char) * (len + 1)); /* space for null term */
365
0
  if(buf == 0) {
366
0
    ser_error = E_OUT_OF_MEM;
367
0
    PKG_MEM_ERROR;
368
0
    return 0;
369
0
  }
370
0
  memcpy(buf, RPORT, RPORT_LEN);
371
0
  memcpy(buf + RPORT_LEN, tmp, tmp_len);
372
0
  buf[len] = 0; /*null terminate it*/
373
374
0
  *rport_len = len;
375
0
  return buf;
376
0
}
377
378
379
char *id_builder(struct sip_msg *msg, unsigned int *id_len)
380
0
{
381
0
  char *buf;
382
0
  int len, value_len;
383
0
  char revhex[sizeof(int) * 2];
384
0
  char *p;
385
0
  int size;
386
387
0
  size = sizeof(int) * 2;
388
0
  p = &revhex[0];
389
0
  if(int2reverse_hex(&p, &size, msg->rcv.proto_reserved1) == -1) {
390
0
    LM_CRIT("not enough space for id\n");
391
0
    return 0;
392
0
  }
393
0
  value_len = p - &revhex[0];
394
0
  len = ID_PARAM_LEN + value_len;
395
0
  buf = pkg_malloc(sizeof(char) * (len + 1)); /* place for ending \0 */
396
0
  if(buf == 0) {
397
0
    ser_error = E_OUT_OF_MEM;
398
0
    PKG_MEM_ERROR;
399
0
    return 0;
400
0
  }
401
0
  memcpy(buf, ID_PARAM, ID_PARAM_LEN);
402
0
  memcpy(buf + ID_PARAM_LEN, revhex, value_len);
403
0
  buf[len] = 0; /* null terminate it */
404
0
  *id_len = len;
405
0
  return buf;
406
0
}
407
408
409
char *clen_builder(struct sip_msg *msg, int *clen_len, int diff, int body_only)
410
0
{
411
0
  char *buf;
412
0
  int len;
413
0
  int value;
414
0
  char *value_s;
415
0
  int value_len;
416
0
  char *body;
417
418
419
0
  body = get_body(msg);
420
0
  if(body == 0) {
421
0
    ser_error = E_BAD_REQ;
422
0
    LM_ERR("no message body found (missing crlf?) [[%.*s]]\n", msg->len,
423
0
        msg->buf);
424
0
    return 0;
425
0
  }
426
0
  value = msg->len - (int)(body - msg->buf) + diff;
427
0
  value_s = int2str(value, &value_len);
428
0
  LM_DBG("content-length: %d (%s)\n", value, value_s);
429
430
0
  if(body_only) {
431
0
    len = value_len;
432
0
  } else {
433
0
    len = CONTENT_LENGTH_LEN + value_len + CRLF_LEN;
434
0
  }
435
0
  buf = pkg_malloc(sizeof(char) * (len + 1));
436
0
  if(buf == 0) {
437
0
    ser_error = E_OUT_OF_MEM;
438
0
    PKG_MEM_ERROR;
439
0
    return 0;
440
0
  }
441
0
  if(body_only) {
442
0
    memcpy(buf, value_s, value_len);
443
0
  } else {
444
0
    memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
445
0
    memcpy(buf + CONTENT_LENGTH_LEN, value_s, value_len);
446
0
    memcpy(buf + CONTENT_LENGTH_LEN + value_len, CRLF, CRLF_LEN);
447
0
  }
448
0
  buf[len] = 0; /* null terminate it */
449
0
  *clen_len = len;
450
0
  return buf;
451
0
}
452
453
454
/* checks if a lump opt condition
455
 * returns 1 if cond is true, 0 if false */
456
static inline int lump_check_opt(
457
    struct lump *l, struct sip_msg *msg, struct dest_info *snd_i)
458
0
{
459
0
  struct ip_addr *ip;
460
0
  unsigned short port;
461
0
  int proto;
462
463
0
#define get_ip_port_proto                                 \
464
0
  if((snd_i == 0) || (snd_i->send_sock == 0)) {         \
465
0
    LM_CRIT("null send socket\n");                    \
466
0
    return 1; /* we presume they are different :-) */ \
467
0
  }                                                     \
468
0
  if(msg->rcv.bind_address) {                           \
469
0
    ip = &msg->rcv.bind_address->address;             \
470
0
    port = msg->rcv.bind_address->port_no;            \
471
0
    proto = msg->rcv.bind_address->proto;             \
472
0
  } else {                                              \
473
0
    ip = &msg->rcv.dst_ip;                            \
474
0
    port = msg->rcv.dst_port;                         \
475
0
    proto = msg->rcv.proto;                           \
476
0
  }
477
478
0
  switch(l->u.cond) {
479
0
    case COND_FALSE:
480
0
      return 0;
481
0
    case COND_TRUE:
482
0
      LUMP_SET_COND_TRUE(l);
483
0
      return 1;
484
0
    case COND_IF_DIFF_REALMS:
485
0
      get_ip_port_proto;
486
      /* faster tests first */
487
0
      if((port == snd_i->send_sock->port_no)
488
0
          && (proto == snd_i->send_sock->proto)
489
0
          && (msg->rcv.proto == snd_i->proto) &&
490
#ifdef USE_COMP
491
          (msg->rcv.comp == snd_i->comp) &&
492
#endif
493
0
          (ip_addr_cmp(ip, &snd_i->send_sock->address)))
494
0
        return 0;
495
0
      else {
496
0
        LUMP_SET_COND_TRUE(l);
497
0
        return 1;
498
0
      }
499
0
    case COND_IF_DIFF_AF:
500
0
      get_ip_port_proto;
501
0
      if(ip->af != snd_i->send_sock->address.af) {
502
0
        LUMP_SET_COND_TRUE(l);
503
0
        return 1;
504
0
      } else
505
0
        return 0;
506
0
    case COND_IF_DIFF_PROTO:
507
0
      get_ip_port_proto;
508
0
      if((proto != snd_i->send_sock->proto)
509
0
          || (msg->rcv.proto != snd_i->proto)) {
510
0
        LUMP_SET_COND_TRUE(l);
511
0
        return 1;
512
0
      } else
513
0
        return 0;
514
0
    case COND_IF_DIFF_PORT:
515
0
      get_ip_port_proto;
516
0
      if(port != snd_i->send_sock->port_no) {
517
0
        LUMP_SET_COND_TRUE(l);
518
0
        return 1;
519
0
      } else
520
0
        return 0;
521
0
    case COND_IF_DIFF_IP:
522
0
      get_ip_port_proto;
523
0
      if(ip_addr_cmp(ip, &snd_i->send_sock->address))
524
0
        return 0;
525
0
      else {
526
0
        LUMP_SET_COND_TRUE(l);
527
0
        return 1;
528
0
      }
529
0
    case COND_IF_RAND:
530
0
      if(kam_rand() >= KAM_RAND_MAX / 2) {
531
0
        LUMP_SET_COND_TRUE(l);
532
0
        return 1;
533
0
      } else
534
0
        return 0;
535
0
    default:
536
0
      LM_CRIT("unknown lump condition %d\n", l->u.cond);
537
0
  }
538
0
  return 0; /* false */
539
0
}
540
541
542
/* computes the "unpacked" len of a lump list,
543
   code moved from build_req_from_req */
544
static inline int lumps_len(
545
    struct sip_msg *msg, struct lump *lumps, struct dest_info *send_info)
546
0
{
547
0
  int s_offset;
548
0
  int new_len;
549
0
  struct lump *t;
550
0
  struct lump *r;
551
0
  str *send_address_str = NULL;
552
0
  str *send_port_str = NULL;
553
0
  int send_proto_id = PROTO_NONE;
554
0
  int send_af = 0;
555
0
  str *recv_address_str = NULL;
556
0
  str *recv_port_str = NULL;
557
0
  int recv_port_no = 0;
558
0
  int recv_proto_id = PROTO_NONE;
559
0
  int recv_af = 0;
560
0
  struct socket_info *send_sock;
561
562
563
#ifdef USE_COMP
564
#define RCVCOMP_LUMP_LEN                                  \
565
  /* add;comp=xxx */                                    \
566
  switch(msg->rcv.comp) {                               \
567
    case COMP_NONE:                                   \
568
      break;                                        \
569
    case COMP_SIGCOMP:                                \
570
      new_len += COMP_PARAM_LEN + SIGCOMP_NAME_LEN; \
571
      break;                                        \
572
    case COMP_SERGZ:                                  \
573
      new_len += COMP_PARAM_LEN + SERGZ_NAME_LEN;   \
574
      break;                                        \
575
    default:                                          \
576
      LM_CRIT("unknown comp %d\n", msg->rcv.comp);  \
577
  }
578
579
#define SENDCOMP_LUMP_LEN                                  \
580
  /* add;comp=xxx */                                     \
581
  switch(send_info->comp) {                              \
582
    case COMP_NONE:                                    \
583
      break;                                         \
584
    case COMP_SIGCOMP:                                 \
585
      new_len += COMP_PARAM_LEN + SIGCOMP_NAME_LEN;  \
586
      break;                                         \
587
    case COMP_SERGZ:                                   \
588
      new_len += COMP_PARAM_LEN + SERGZ_NAME_LEN;    \
589
      break;                                         \
590
    default:                                           \
591
      LM_CRIT("unknown comp %d\n", send_info->comp); \
592
  }
593
#else
594
0
#define RCVCOMP_LUMP_LEN
595
0
#define SENDCOMP_LUMP_LEN
596
0
#endif /*USE_COMP */
597
598
0
#define SUBST_LUMP_LEN(subst_l)                                              \
599
0
  switch((subst_l)->u.subst) {                                             \
600
0
    case SUBST_RCV_IP:                                                   \
601
0
      if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) {     \
602
0
        new_len += recv_address_str->len;                            \
603
0
        if(recv_af == AF_INET6)                                      \
604
0
          new_len += 2;                                            \
605
0
      } else {                                                         \
606
0
        LM_CRIT("rcv ip - null bind_address\n");                     \
607
0
      };                                                               \
608
0
      break;                                                           \
609
0
    case SUBST_RCV_PORT:                                                 \
610
0
      if(msg->rcv.bind_address && STR_WITHVAL(recv_port_str)) {        \
611
0
        new_len += recv_port_str->len;                               \
612
0
      } else {                                                         \
613
0
        LM_CRIT(" rcv port - null bind_address\n");                  \
614
0
      };                                                               \
615
0
      break;                                                           \
616
0
    case SUBST_RCV_PROTO:                                                \
617
0
      if(msg->rcv.bind_address) {                                      \
618
0
        switch(msg->rcv.bind_address->proto) {                       \
619
0
          case PROTO_NONE:                                         \
620
0
          case PROTO_UDP:                                          \
621
0
            new_len += 3;                                        \
622
0
            break;                                               \
623
0
          case PROTO_TCP:                                          \
624
0
          case PROTO_TLS:                                          \
625
0
            switch(msg->rcv.proto) {                             \
626
0
              case PROTO_WS:                                   \
627
0
              case PROTO_WSS:                                  \
628
0
                new_len += 2;                                \
629
0
                break;                                       \
630
0
              default:                                         \
631
0
                new_len += 3;                                \
632
0
                break;                                       \
633
0
            }                                                    \
634
0
            break;                                               \
635
0
          case PROTO_SCTP:                                         \
636
0
            new_len += 4;                                        \
637
0
            break;                                               \
638
0
          default:                                                 \
639
0
            LM_CRIT("unknown proto %d\n",                        \
640
0
                msg->rcv.bind_address->proto);               \
641
0
        }                                                            \
642
0
      } else {                                                         \
643
0
        LM_CRIT("null bind_address\n");                              \
644
0
      };                                                               \
645
0
      break;                                                           \
646
0
    case SUBST_RCV_ALL:                                                  \
647
0
    case SUBST_RCV_ALL_EX:                                               \
648
0
      if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) {     \
649
0
        new_len += recv_address_str->len;                            \
650
0
        if((recv_af == AF_INET6) && (recv_address_str->s[0] != '[')  \
651
0
            && (memchr(recv_address_str->s, ':',                 \
652
0
                  recv_address_str->len)                   \
653
0
                != NULL))                                    \
654
0
          new_len += 2;                                            \
655
0
        if(recv_port_no != SIP_PORT && STR_WITHVAL(recv_port_str)) { \
656
          /* add :port_no */                                       \
657
0
          new_len += 1 + recv_port_str->len;                       \
658
0
        }                                                            \
659
        /*add;transport=xxx*/                                        \
660
0
        switch(recv_proto_id) {                                      \
661
0
          case PROTO_NONE:                                         \
662
0
          case PROTO_UDP:                                          \
663
0
            break; /* udp is the default */                      \
664
0
          case PROTO_TCP:                                          \
665
0
          case PROTO_TLS:                                          \
666
0
            switch(msg->rcv.proto) {                             \
667
0
              case PROTO_WS:                                   \
668
0
              case PROTO_WSS:                                  \
669
0
                new_len += TRANSPORT_PARAM_LEN + 2;          \
670
0
                break;                                       \
671
0
              default:                                         \
672
0
                new_len += TRANSPORT_PARAM_LEN + 3;          \
673
0
                break;                                       \
674
0
            }                                                    \
675
0
            break;                                               \
676
0
          case PROTO_WS:                                           \
677
0
          case PROTO_WSS:                                          \
678
0
            new_len += TRANSPORT_PARAM_LEN + 2;                  \
679
0
            break;                                               \
680
0
          case PROTO_SCTP:                                         \
681
0
            new_len += TRANSPORT_PARAM_LEN + 4;                  \
682
0
            break;                                               \
683
0
          default:                                                 \
684
0
            LM_CRIT("unknown proto %d\n",                        \
685
0
                msg->rcv.bind_address->proto);               \
686
0
        }                                                            \
687
0
        if((subst_l)->u.subst == SUBST_RCV_ALL_EX                    \
688
0
            && msg->rcv.bind_address->sockname.len > 0) {        \
689
0
          new_len += SOCKNAME_PARAM_LEN                            \
690
0
                 + msg->rcv.bind_address->sockname.len;        \
691
0
        }                                                            \
692
0
        RCVCOMP_LUMP_LEN                                             \
693
0
      } else {                                                         \
694
0
        LM_CRIT("null bind_address\n");                              \
695
0
      };                                                               \
696
0
      break;                                                           \
697
0
    case SUBST_SND_IP:                                                   \
698
0
      if(send_sock) {                                                  \
699
0
        new_len += send_address_str->len;                            \
700
0
        if(send_af == AF_INET6 && send_address_str->s[0] != '[')     \
701
0
          new_len += 2;                                            \
702
0
      } else {                                                         \
703
0
        LM_CRIT("null send_sock\n");                                 \
704
0
      };                                                               \
705
0
      break;                                                           \
706
0
    case SUBST_SND_PORT:                                                 \
707
0
      if(send_sock) {                                                  \
708
0
        new_len += send_port_str->len;                               \
709
0
      } else {                                                         \
710
0
        LM_CRIT("null send_sock\n");                                 \
711
0
      };                                                               \
712
0
      break;                                                           \
713
0
    case SUBST_SND_PROTO:                                                \
714
0
      if(send_sock) {                                                  \
715
0
        switch(send_sock->proto) {                                   \
716
0
          case PROTO_NONE:                                         \
717
0
          case PROTO_UDP:                                          \
718
0
            new_len += 3;                                        \
719
0
            break;                                               \
720
0
          case PROTO_TCP:                                          \
721
0
          case PROTO_TLS:                                          \
722
0
            switch(send_info->proto) {                           \
723
0
              case PROTO_WS:                                   \
724
0
              case PROTO_WSS:                                  \
725
0
                new_len += 2;                                \
726
0
                break;                                       \
727
0
              default:                                         \
728
0
                new_len += 3;                                \
729
0
                break;                                       \
730
0
            }                                                    \
731
0
            break;                                               \
732
0
          case PROTO_SCTP:                                         \
733
0
            new_len += 4;                                        \
734
0
            break;                                               \
735
0
          default:                                                 \
736
0
            LM_CRIT("unknown proto %d\n", send_sock->proto);     \
737
0
        }                                                            \
738
0
      } else {                                                         \
739
0
        LM_CRIT("null send_sock\n");                                 \
740
0
      };                                                               \
741
0
      break;                                                           \
742
0
    case SUBST_SND_ALL:                                                  \
743
0
    case SUBST_SND_ALL_EX:                                               \
744
0
      if(send_sock) {                                                  \
745
0
        new_len += send_address_str->len;                            \
746
0
        if((send_af == AF_INET6) && (send_address_str->s[0] != '[')  \
747
0
            && (memchr(send_address_str->s, ':',                 \
748
0
                  send_address_str->len)                   \
749
0
                != NULL))                                    \
750
0
          new_len += 2;                                            \
751
0
        if((send_sock->port_no != SIP_PORT)                          \
752
0
            || (send_port_str != &(send_sock->port_no_str))) {   \
753
          /* add :port_no */                                       \
754
0
          new_len += 1 + send_port_str->len;                       \
755
0
        }                                                            \
756
        /*add;transport=xxx*/                                        \
757
0
        switch(send_proto_id) {                                      \
758
0
          case PROTO_NONE:                                         \
759
0
          case PROTO_UDP:                                          \
760
0
            break; /* udp is the default */                      \
761
0
          case PROTO_TCP:                                          \
762
0
          case PROTO_TLS:                                          \
763
0
            switch(send_info->proto) {                           \
764
0
              case PROTO_WS:                                   \
765
0
              case PROTO_WSS:                                  \
766
0
                new_len += TRANSPORT_PARAM_LEN + 2;          \
767
0
                break;                                       \
768
0
              default:                                         \
769
0
                new_len += TRANSPORT_PARAM_LEN + 3;          \
770
0
                break;                                       \
771
0
            }                                                    \
772
0
            break;                                               \
773
0
          case PROTO_WS:                                           \
774
0
          case PROTO_WSS:                                          \
775
0
            new_len += TRANSPORT_PARAM_LEN + 2;                  \
776
0
            break;                                               \
777
0
          case PROTO_SCTP:                                         \
778
0
            new_len += TRANSPORT_PARAM_LEN + 4;                  \
779
0
            break;                                               \
780
0
          default:                                                 \
781
0
            LM_CRIT("unknown proto %d\n", send_sock->proto);     \
782
0
        }                                                            \
783
0
        if((subst_l)->u.subst == SUBST_SND_ALL_EX                    \
784
0
            && send_sock->sockname.len > 0) {                    \
785
0
          new_len += SOCKNAME_PARAM_LEN + send_sock->sockname.len; \
786
0
        }                                                            \
787
0
        SENDCOMP_LUMP_LEN                                            \
788
0
      } else {                                                         \
789
0
        LM_CRIT("null send_sock\n");                                 \
790
0
      };                                                               \
791
0
      break;                                                           \
792
0
    case SUBST_NOP: /* do nothing */                                     \
793
0
      break;                                                           \
794
0
    default:                                                             \
795
0
      LM_CRIT("unknown subst type %d\n", (subst_l)->u.subst);          \
796
0
  }
797
798
0
  if(send_info) {
799
0
    send_sock = send_info->send_sock;
800
0
  } else {
801
0
    send_sock = 0;
802
0
  };
803
0
  s_offset = 0;
804
0
  new_len = 0;
805
  /* init send_address_str & send_port_str */
806
0
  if(send_sock && send_sock->useinfo.name.len > 0) {
807
0
    send_address_str = &(send_sock->useinfo.name);
808
0
    send_af = send_sock->useinfo.af;
809
0
  } else if(msg->set_global_address.len) {
810
0
    send_address_str = &(msg->set_global_address);
811
0
    if(send_sock) {
812
0
      send_af = send_sock->address.af;
813
0
    }
814
0
  } else if(send_sock) {
815
0
    send_address_str = &(send_sock->address_str);
816
0
    send_af = send_sock->address.af;
817
0
  }
818
0
  if(send_sock && send_sock->useinfo.port_no > 0)
819
0
    send_port_str = &(send_sock->useinfo.port_no_str);
820
0
  else if(msg->set_global_port.len)
821
0
    send_port_str = &(msg->set_global_port);
822
0
  else
823
0
    send_port_str = &(send_sock->port_no_str);
824
0
  if(send_sock) {
825
0
    if(send_sock->useinfo.proto != PROTO_NONE)
826
0
      send_proto_id = send_sock->useinfo.proto;
827
0
    else
828
0
      send_proto_id = send_sock->proto;
829
0
  }
830
  /* init recv_address_str, recv_port_str & recv_port_no */
831
0
  if(msg->rcv.bind_address) {
832
0
    if(msg->rcv.bind_address->useinfo.name.len > 0) {
833
0
      recv_address_str = &(msg->rcv.bind_address->useinfo.name);
834
0
      recv_af = msg->rcv.bind_address->useinfo.af;
835
0
    } else {
836
0
      recv_address_str = &(msg->rcv.bind_address->address_str);
837
0
      recv_af = msg->rcv.bind_address->address.af;
838
0
    }
839
0
    if(msg->rcv.bind_address->useinfo.port_no > 0) {
840
0
      recv_port_str = &(msg->rcv.bind_address->useinfo.port_no_str);
841
0
      recv_port_no = msg->rcv.bind_address->useinfo.port_no;
842
0
    } else {
843
0
      recv_port_str = &(msg->rcv.bind_address->port_no_str);
844
0
      recv_port_no = msg->rcv.bind_address->port_no;
845
0
    }
846
0
    if(msg->rcv.bind_address->useinfo.proto != PROTO_NONE) {
847
0
      recv_proto_id = msg->rcv.bind_address->useinfo.proto;
848
0
    } else {
849
0
      recv_proto_id = msg->rcv.bind_address->proto;
850
0
    }
851
0
  }
852
853
0
  for(t = lumps; t; t = t->next) {
854
    /* skip if this is an OPT lump and the condition is not satisfied */
855
0
    if((t->op == LUMP_ADD_OPT) && !lump_check_opt(t, msg, send_info))
856
0
      continue;
857
0
    for(r = t->before; r; r = r->before) {
858
0
      switch(r->op) {
859
0
        case LUMP_ADD:
860
0
          new_len += r->len;
861
0
          break;
862
0
        case LUMP_ADD_SUBST:
863
0
          SUBST_LUMP_LEN(r);
864
0
          break;
865
0
        case LUMP_ADD_OPT:
866
          /* skip if this is an OPT lump and the condition is
867
           * not satisfied */
868
0
          if(!lump_check_opt(r, msg, send_info))
869
0
            goto skip_before;
870
0
          break;
871
0
        default:
872
          /* only ADD allowed for before/after */
873
0
          LM_CRIT("invalid op for data lump (%x)\n", r->op);
874
0
      }
875
0
    }
876
0
  skip_before:
877
0
    switch(t->op) {
878
0
      case LUMP_ADD:
879
0
        new_len += t->len;
880
0
        break;
881
0
      case LUMP_ADD_SUBST:
882
0
        SUBST_LUMP_LEN(t);
883
0
        break;
884
0
      case LUMP_ADD_OPT:
885
        /* we don't do anything here, it's only a condition for
886
         * before & after */
887
0
        break;
888
0
      case LUMP_DEL:
889
        /* fix overlapping deleted zones */
890
0
        if(t->u.offset < s_offset) {
891
          /* change len */
892
0
          if(t->len > s_offset - t->u.offset)
893
0
            t->len -= s_offset - t->u.offset;
894
0
          else
895
0
            t->len = 0;
896
0
          t->u.offset = s_offset;
897
0
        }
898
0
        s_offset = t->u.offset + t->len;
899
0
        new_len -= t->len;
900
0
        break;
901
0
      case LUMP_NOP:
902
        /* fix offset if overlapping on a deleted zone */
903
0
        if(t->u.offset < s_offset) {
904
0
          t->u.offset = s_offset;
905
0
        } else
906
0
          s_offset = t->u.offset;
907
        /* do nothing */
908
0
        break;
909
0
      default:
910
0
        LM_CRIT("invalid op for data lump (%x)\n", r->op);
911
0
    }
912
0
    for(r = t->after; r; r = r->after) {
913
0
      switch(r->op) {
914
0
        case LUMP_ADD:
915
0
          new_len += r->len;
916
0
          break;
917
0
        case LUMP_ADD_SUBST:
918
0
          SUBST_LUMP_LEN(r);
919
0
          break;
920
0
        case LUMP_ADD_OPT:
921
          /* skip if this is an OPT lump and the condition is
922
           * not satisfied */
923
0
          if(!lump_check_opt(r, msg, send_info))
924
0
            goto skip_after;
925
0
          break;
926
0
        default:
927
          /* only ADD allowed for before/after */
928
0
          LM_CRIT("invalid op for data lump (%x)\n", r->op);
929
0
      }
930
0
    }
931
0
  skip_after:; /* to make gcc 3.* happy */
932
0
  }
933
0
  return new_len;
934
0
#undef RCVCOMP_LUMP_LEN
935
0
#undef SENDCOMP_LUMP_LEN
936
0
}
937
938
939
/* another helper functions, adds/Removes the lump,
940
  code moved form build_req_from_req  */
941
942
void process_lumps(struct sip_msg *msg, struct lump *lumps, char *new_buf,
943
    unsigned int *new_buf_offs, unsigned int *orig_offs,
944
    struct dest_info *send_info, int flag)
945
0
{
946
0
  struct lump *t;
947
0
  struct lump *r;
948
0
  char *orig;
949
0
  int size;
950
0
  int offset;
951
0
  int s_offset;
952
0
  str *send_address_str = NULL;
953
0
  str *send_port_str = NULL;
954
0
  int send_proto_id = PROTO_NONE;
955
0
  int send_af = 0;
956
0
  str *recv_address_str = NULL;
957
0
  str *recv_port_str = NULL;
958
0
  int recv_port_no = 0;
959
0
  int recv_proto_id = PROTO_NONE;
960
0
  int recv_af = 0;
961
0
  struct socket_info *send_sock;
962
963
#ifdef USE_COMP
964
#define RCVCOMP_PARAM_ADD                                             \
965
  /* add ;comp=xxxx */                                              \
966
  switch(msg->rcv.comp) {                                           \
967
    case COMP_NONE:                                               \
968
      break;                                                    \
969
    case COMP_SIGCOMP:                                            \
970
      memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN);     \
971
      offset += COMP_PARAM_LEN;                                 \
972
      memcpy(new_buf + offset, SIGCOMP_NAME, SIGCOMP_NAME_LEN); \
973
      offset += SIGCOMP_NAME_LEN;                               \
974
      break;                                                    \
975
    case COMP_SERGZ:                                              \
976
      memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN);     \
977
      offset += COMP_PARAM_LEN;                                 \
978
      memcpy(new_buf + offset, SERGZ_NAME, SERGZ_NAME_LEN);     \
979
      offset += SERGZ_NAME_LEN;                                 \
980
      break;                                                    \
981
    default:                                                      \
982
      LM_CRIT("unknown comp %d\n", msg->rcv.comp);              \
983
  }
984
985
#define SENDCOMP_PARAM_ADD                                            \
986
  /* add ;comp=xxxx */                                              \
987
  switch(send_info->comp) {                                         \
988
    case COMP_NONE:                                               \
989
      break;                                                    \
990
    case COMP_SIGCOMP:                                            \
991
      memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN);     \
992
      offset += COMP_PARAM_LEN;                                 \
993
      memcpy(new_buf + offset, SIGCOMP_NAME, SIGCOMP_NAME_LEN); \
994
      offset += SIGCOMP_NAME_LEN;                               \
995
      break;                                                    \
996
    case COMP_SERGZ:                                              \
997
      memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN);     \
998
      offset += COMP_PARAM_LEN;                                 \
999
      memcpy(new_buf + offset, SERGZ_NAME, SERGZ_NAME_LEN);     \
1000
      offset += SERGZ_NAME_LEN;                                 \
1001
      break;                                                    \
1002
    default:                                                      \
1003
      LM_CRIT("unknown comp %d\n", msg->rcv.comp);              \
1004
  }
1005
#else
1006
0
#define RCVCOMP_PARAM_ADD
1007
0
#define SENDCOMP_PARAM_ADD
1008
0
#endif /* USE_COMP */
1009
1010
0
#define SUBST_LUMP(subst_l)                                                    \
1011
0
  switch((subst_l)->u.subst) {                                               \
1012
0
    case SUBST_RCV_IP:                                                     \
1013
0
      if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) {       \
1014
0
        if(recv_af == AF_INET6) {                                      \
1015
0
          new_buf[offset] = '[';                                     \
1016
0
          offset++;                                                  \
1017
0
        }                                                              \
1018
0
        memcpy(new_buf + offset, recv_address_str->s,                  \
1019
0
            recv_address_str->len);                                \
1020
0
        offset += recv_address_str->len;                               \
1021
0
        if(recv_af == AF_INET6) {                                      \
1022
0
          new_buf[offset] = ']';                                     \
1023
0
          offset++;                                                  \
1024
0
        }                                                              \
1025
0
      } else {                                                           \
1026
0
        LM_CRIT("null bind_address\n");                                \
1027
0
      };                                                                 \
1028
0
      break;                                                             \
1029
0
    case SUBST_RCV_PORT:                                                   \
1030
0
      if(msg->rcv.bind_address && STR_WITHVAL(recv_port_str)) {          \
1031
0
        memcpy(new_buf + offset, recv_port_str->s,                     \
1032
0
            recv_port_str->len);                                   \
1033
0
        offset += recv_port_str->len;                                  \
1034
0
      } else {                                                           \
1035
0
        LM_CRIT("null bind_address\n");                                \
1036
0
      };                                                                 \
1037
0
      break;                                                             \
1038
0
    case SUBST_RCV_ALL:                                                    \
1039
0
    case SUBST_RCV_ALL_EX:                                                 \
1040
0
      if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) {       \
1041
        /* address */                                                  \
1042
0
        if((recv_af == AF_INET6) && (recv_address_str->s[0] != '[')    \
1043
0
            && (memchr(recv_address_str->s, ':',                   \
1044
0
                  recv_address_str->len)                     \
1045
0
                != NULL)) {                                    \
1046
0
          new_buf[offset] = '[';                                     \
1047
0
          offset++;                                                  \
1048
0
        }                                                              \
1049
0
        memcpy(new_buf + offset, recv_address_str->s,                  \
1050
0
            recv_address_str->len);                                \
1051
0
        offset += recv_address_str->len;                               \
1052
0
        if((recv_af == AF_INET6) && (recv_address_str->s[0] != '[')    \
1053
0
            && (memchr(recv_address_str->s, ':',                   \
1054
0
                  recv_address_str->len)                     \
1055
0
                != NULL)) {                                    \
1056
0
          new_buf[offset] = ']';                                     \
1057
0
          offset++;                                                  \
1058
0
        }                                                              \
1059
        /* :port */                                                    \
1060
0
        if(recv_port_no != SIP_PORT && STR_WITHVAL(recv_port_str)) {   \
1061
0
          new_buf[offset] = ':';                                     \
1062
0
          offset++;                                                  \
1063
0
          memcpy(new_buf + offset, recv_port_str->s,                 \
1064
0
              recv_port_str->len);                               \
1065
0
          offset += recv_port_str->len;                              \
1066
0
        }                                                              \
1067
0
        switch(recv_proto_id) {                                        \
1068
0
          case PROTO_NONE:                                           \
1069
0
          case PROTO_UDP:                                            \
1070
0
            break; /* nothing to do, udp is default*/              \
1071
0
          case PROTO_TCP:                                            \
1072
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1073
0
                TRANSPORT_PARAM_LEN);                          \
1074
0
            offset += TRANSPORT_PARAM_LEN;                         \
1075
0
            if(msg->rcv.proto == PROTO_WS) {                       \
1076
0
              memcpy(new_buf + offset, "ws", 2);                 \
1077
0
              offset += 2;                                       \
1078
0
            } else {                                               \
1079
0
              memcpy(new_buf + offset, "tcp", 3);                \
1080
0
              offset += 3;                                       \
1081
0
            }                                                      \
1082
0
            break;                                                 \
1083
0
          case PROTO_TLS:                                            \
1084
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1085
0
                TRANSPORT_PARAM_LEN);                          \
1086
0
            offset += TRANSPORT_PARAM_LEN;                         \
1087
0
            if(msg->rcv.proto == PROTO_WS                          \
1088
0
                || msg->rcv.proto == PROTO_WSS) {              \
1089
0
              memcpy(new_buf + offset, "ws", 2);                 \
1090
0
              offset += 2;                                       \
1091
0
            } else {                                               \
1092
0
              memcpy(new_buf + offset, "tls", 3);                \
1093
0
              offset += 3;                                       \
1094
0
            }                                                      \
1095
0
            break;                                                 \
1096
0
          case PROTO_WS:                                             \
1097
0
          case PROTO_WSS:                                            \
1098
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1099
0
                TRANSPORT_PARAM_LEN);                          \
1100
0
            offset += TRANSPORT_PARAM_LEN;                         \
1101
0
            memcpy(new_buf + offset, "ws", 2);                     \
1102
0
            offset += 2;                                           \
1103
0
            break;                                                 \
1104
0
          case PROTO_SCTP:                                           \
1105
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1106
0
                TRANSPORT_PARAM_LEN);                          \
1107
0
            offset += TRANSPORT_PARAM_LEN;                         \
1108
0
            memcpy(new_buf + offset, "sctp", 4);                   \
1109
0
            offset += 4;                                           \
1110
0
            break;                                                 \
1111
0
          default:                                                   \
1112
0
            LM_CRIT("unknown proto %d\n",                          \
1113
0
                msg->rcv.bind_address->proto);                 \
1114
0
        }                                                              \
1115
0
        if((subst_l)->u.subst == SUBST_RCV_ALL_EX                      \
1116
0
            && msg->rcv.bind_address->sockname.len > 0) {          \
1117
0
          memcpy(new_buf + offset, SOCKNAME_PARAM,                   \
1118
0
              SOCKNAME_PARAM_LEN);                               \
1119
0
          offset += SOCKNAME_PARAM_LEN;                              \
1120
0
          memcpy(new_buf + offset,                                   \
1121
0
              msg->rcv.bind_address->sockname.s,                 \
1122
0
              msg->rcv.bind_address->sockname.len);              \
1123
0
          offset += msg->rcv.bind_address->sockname.len;             \
1124
0
        }                                                              \
1125
0
        RCVCOMP_PARAM_ADD                                              \
1126
0
      } else {                                                           \
1127
0
        LM_CRIT("null bind_address\n");                                \
1128
0
      };                                                                 \
1129
0
      break;                                                             \
1130
0
    case SUBST_SND_IP:                                                     \
1131
0
      if(send_sock) {                                                    \
1132
0
        if((send_af == AF_INET6) && (send_address_str->s[0] != '[')) { \
1133
0
          new_buf[offset] = '[';                                     \
1134
0
          offset++;                                                  \
1135
0
        }                                                              \
1136
0
        memcpy(new_buf + offset, send_address_str->s,                  \
1137
0
            send_address_str->len);                                \
1138
0
        offset += send_address_str->len;                               \
1139
0
        if((send_af == AF_INET6) && (send_address_str->s[0] != '[')) { \
1140
0
          new_buf[offset] = ']';                                     \
1141
0
          offset++;                                                  \
1142
0
        }                                                              \
1143
0
      } else {                                                           \
1144
0
        LM_CRIT("null send_sock\n");                                   \
1145
0
      };                                                                 \
1146
0
      break;                                                             \
1147
0
    case SUBST_SND_PORT:                                                   \
1148
0
      if(send_sock) {                                                    \
1149
0
        memcpy(new_buf + offset, send_port_str->s,                     \
1150
0
            send_port_str->len);                                   \
1151
0
        offset += send_port_str->len;                                  \
1152
0
      } else {                                                           \
1153
0
        LM_CRIT("null send_sock\n");                                   \
1154
0
      };                                                                 \
1155
0
      break;                                                             \
1156
0
    case SUBST_SND_ALL:                                                    \
1157
0
    case SUBST_SND_ALL_EX:                                                 \
1158
0
      if(send_sock) {                                                    \
1159
        /* address */                                                  \
1160
0
        if((send_af == AF_INET6) && (send_address_str->s[0] != '[')    \
1161
0
            && (memchr(send_address_str->s, ':',                   \
1162
0
                  send_address_str->len)                     \
1163
0
                != NULL)) {                                    \
1164
0
          new_buf[offset] = '[';                                     \
1165
0
          offset++;                                                  \
1166
0
        }                                                              \
1167
0
        memcpy(new_buf + offset, send_address_str->s,                  \
1168
0
            send_address_str->len);                                \
1169
0
        offset += send_address_str->len;                               \
1170
0
        if((send_af == AF_INET6) && (send_address_str->s[0] != '[')    \
1171
0
            && (memchr(send_address_str->s, ':',                   \
1172
0
                  send_address_str->len)                     \
1173
0
                != NULL)) {                                    \
1174
0
          new_buf[offset] = ']';                                     \
1175
0
          offset++;                                                  \
1176
0
        }                                                              \
1177
        /* :port */                                                    \
1178
0
        if((send_sock->port_no != SIP_PORT)                            \
1179
0
            || (send_port_str != &(send_sock->port_no_str))) {     \
1180
0
          new_buf[offset] = ':';                                     \
1181
0
          offset++;                                                  \
1182
0
          memcpy(new_buf + offset, send_port_str->s,                 \
1183
0
              send_port_str->len);                               \
1184
0
          offset += send_port_str->len;                              \
1185
0
        }                                                              \
1186
0
        switch(send_proto_id) {                                        \
1187
0
          case PROTO_NONE:                                           \
1188
0
          case PROTO_UDP:                                            \
1189
0
            break; /* nothing to do, udp is default*/              \
1190
0
          case PROTO_TCP:                                            \
1191
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1192
0
                TRANSPORT_PARAM_LEN);                          \
1193
0
            offset += TRANSPORT_PARAM_LEN;                         \
1194
0
            if(send_info->proto == PROTO_WS) {                     \
1195
0
              memcpy(new_buf + offset, "ws", 2);                 \
1196
0
              offset += 2;                                       \
1197
0
            } else {                                               \
1198
0
              memcpy(new_buf + offset, "tcp", 3);                \
1199
0
              offset += 3;                                       \
1200
0
            }                                                      \
1201
0
            break;                                                 \
1202
0
          case PROTO_TLS:                                            \
1203
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1204
0
                TRANSPORT_PARAM_LEN);                          \
1205
0
            offset += TRANSPORT_PARAM_LEN;                         \
1206
0
            if(send_info->proto == PROTO_WS                        \
1207
0
                || send_info->proto == PROTO_WSS) {            \
1208
0
              memcpy(new_buf + offset, "ws", 2);                 \
1209
0
              offset += 2;                                       \
1210
0
            } else {                                               \
1211
0
              memcpy(new_buf + offset, "tls", 3);                \
1212
0
              offset += 3;                                       \
1213
0
            }                                                      \
1214
0
            break;                                                 \
1215
0
          case PROTO_WS:                                             \
1216
0
          case PROTO_WSS:                                            \
1217
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1218
0
                TRANSPORT_PARAM_LEN);                          \
1219
0
            offset += TRANSPORT_PARAM_LEN;                         \
1220
0
            memcpy(new_buf + offset, "ws", 2);                     \
1221
0
            offset += 2;                                           \
1222
0
            break;                                                 \
1223
0
          case PROTO_SCTP:                                           \
1224
0
            memcpy(new_buf + offset, TRANSPORT_PARAM,              \
1225
0
                TRANSPORT_PARAM_LEN);                          \
1226
0
            offset += TRANSPORT_PARAM_LEN;                         \
1227
0
            memcpy(new_buf + offset, "sctp", 4);                   \
1228
0
            offset += 4;                                           \
1229
0
            break;                                                 \
1230
0
          default:                                                   \
1231
0
            LM_CRIT("unknown proto %d\n", send_sock->proto);       \
1232
0
        }                                                              \
1233
0
        if((subst_l)->u.subst == SUBST_SND_ALL_EX                      \
1234
0
            && send_sock->sockname.len > 0) {                      \
1235
0
          memcpy(new_buf + offset, SOCKNAME_PARAM,                   \
1236
0
              SOCKNAME_PARAM_LEN);                               \
1237
0
          offset += SOCKNAME_PARAM_LEN;                              \
1238
0
          memcpy(new_buf + offset, send_sock->sockname.s,            \
1239
0
              send_sock->sockname.len);                          \
1240
0
          offset += send_sock->sockname.len;                         \
1241
0
        }                                                              \
1242
0
        SENDCOMP_PARAM_ADD                                             \
1243
0
      } else {                                                           \
1244
0
        LM_CRIT("null bind_address\n");                                \
1245
0
      };                                                                 \
1246
0
      break;                                                             \
1247
0
    case SUBST_RCV_PROTO:                                                  \
1248
0
      if(msg->rcv.bind_address) {                                        \
1249
0
        switch(msg->rcv.bind_address->proto) {                         \
1250
0
          case PROTO_NONE:                                           \
1251
0
          case PROTO_UDP:                                            \
1252
0
            memcpy(new_buf + offset, "udp", 3);                    \
1253
0
            offset += 3;                                           \
1254
0
            break;                                                 \
1255
0
          case PROTO_TCP:                                            \
1256
0
            if(msg->rcv.proto == PROTO_WS) {                       \
1257
0
              memcpy(new_buf + offset, "ws", 2);                 \
1258
0
              offset += 2;                                       \
1259
0
            } else {                                               \
1260
0
              memcpy(new_buf + offset, "tcp", 3);                \
1261
0
              offset += 3;                                       \
1262
0
            }                                                      \
1263
0
            break;                                                 \
1264
0
          case PROTO_TLS:                                            \
1265
0
            if(msg->rcv.proto == PROTO_WS                          \
1266
0
                || msg->rcv.proto == PROTO_WSS) {              \
1267
0
              memcpy(new_buf + offset, "ws", 2);                 \
1268
0
              offset += 2;                                       \
1269
0
            } else {                                               \
1270
0
              memcpy(new_buf + offset, "tls", 3);                \
1271
0
              offset += 3;                                       \
1272
0
            }                                                      \
1273
0
            break;                                                 \
1274
0
          case PROTO_SCTP:                                           \
1275
0
            memcpy(new_buf + offset, "sctp", 4);                   \
1276
0
            offset += 4;                                           \
1277
0
            break;                                                 \
1278
0
          default:                                                   \
1279
0
            LM_CRIT("unknown proto %d\n",                          \
1280
0
                msg->rcv.bind_address->proto);                 \
1281
0
        }                                                              \
1282
0
      } else {                                                           \
1283
0
        LM_CRIT("null send_sock\n");                                   \
1284
0
      };                                                                 \
1285
0
      break;                                                             \
1286
0
    case SUBST_SND_PROTO:                                                  \
1287
0
      if(send_sock) {                                                    \
1288
0
        switch(send_sock->proto) {                                     \
1289
0
          case PROTO_NONE:                                           \
1290
0
          case PROTO_UDP:                                            \
1291
0
            memcpy(new_buf + offset, "udp", 3);                    \
1292
0
            offset += 3;                                           \
1293
0
            break;                                                 \
1294
0
          case PROTO_TCP:                                            \
1295
0
            if(send_info->proto == PROTO_WS) {                     \
1296
0
              memcpy(new_buf + offset, "ws", 2);                 \
1297
0
              offset += 2;                                       \
1298
0
            } else {                                               \
1299
0
              memcpy(new_buf + offset, "tcp", 3);                \
1300
0
              offset += 3;                                       \
1301
0
            }                                                      \
1302
0
            break;                                                 \
1303
0
          case PROTO_TLS:                                            \
1304
0
            if(send_info->proto == PROTO_WS                        \
1305
0
                || send_info->proto == PROTO_WSS) {            \
1306
0
              memcpy(new_buf + offset, "ws", 2);                 \
1307
0
              offset += 2;                                       \
1308
0
            } else {                                               \
1309
0
              memcpy(new_buf + offset, "tls", 3);                \
1310
0
              offset += 3;                                       \
1311
0
            }                                                      \
1312
0
            break;                                                 \
1313
0
          case PROTO_SCTP:                                           \
1314
0
            memcpy(new_buf + offset, "sctp", 4);                   \
1315
0
            offset += 4;                                           \
1316
0
            break;                                                 \
1317
0
          default:                                                   \
1318
0
            LM_CRIT("unknown proto %d\n", send_sock->proto);       \
1319
0
        }                                                              \
1320
0
      } else {                                                           \
1321
0
        LM_CRIT("null send_sock\n");                                   \
1322
0
      };                                                                 \
1323
0
      break;                                                             \
1324
0
    default:                                                               \
1325
0
      LM_CRIT("unknown subst type %d\n", (subst_l)->u.subst);            \
1326
0
  }
1327
1328
0
  if(send_info) {
1329
0
    send_sock = send_info->send_sock;
1330
0
  } else {
1331
0
    send_sock = 0;
1332
0
  }
1333
  /* init send_address_str & send_port_str */
1334
0
  if(send_sock && send_sock->useinfo.name.len > 0) {
1335
0
    send_address_str = &(send_sock->useinfo.name);
1336
0
    send_af = send_sock->useinfo.af;
1337
0
  } else if(msg->set_global_address.len) {
1338
0
    send_address_str = &(msg->set_global_address);
1339
0
    if(send_sock) {
1340
0
      send_af = send_sock->address.af;
1341
0
    }
1342
0
  } else if(send_sock) {
1343
0
    send_address_str = &(send_sock->address_str);
1344
0
    send_af = send_sock->address.af;
1345
0
  }
1346
0
  if(send_sock && send_sock->useinfo.port_no > 0)
1347
0
    send_port_str = &(send_sock->useinfo.port_no_str);
1348
0
  else if(msg->set_global_port.len)
1349
0
    send_port_str = &(msg->set_global_port);
1350
0
  else
1351
0
    send_port_str = &(send_sock->port_no_str);
1352
0
  if(send_sock) {
1353
0
    if(send_sock->useinfo.proto != PROTO_NONE)
1354
0
      send_proto_id = send_sock->useinfo.proto;
1355
0
    else
1356
0
      send_proto_id = send_sock->proto;
1357
0
  }
1358
  /* init recv_address_str, recv_port_str & recv_port_no */
1359
0
  if(msg->rcv.bind_address) {
1360
0
    if(msg->rcv.bind_address->useinfo.name.len > 0) {
1361
0
      recv_address_str = &(msg->rcv.bind_address->useinfo.name);
1362
0
      recv_af = msg->rcv.bind_address->useinfo.af;
1363
0
    } else {
1364
0
      recv_address_str = &(msg->rcv.bind_address->address_str);
1365
0
      recv_af = msg->rcv.bind_address->address.af;
1366
0
    }
1367
0
    if(msg->rcv.bind_address->useinfo.port_no > 0) {
1368
0
      recv_port_str = &(msg->rcv.bind_address->useinfo.port_no_str);
1369
0
      recv_port_no = msg->rcv.bind_address->useinfo.port_no;
1370
0
    } else {
1371
0
      recv_port_str = &(msg->rcv.bind_address->port_no_str);
1372
0
      recv_port_no = msg->rcv.bind_address->port_no;
1373
0
    }
1374
0
    if(msg->rcv.bind_address->useinfo.proto != PROTO_NONE) {
1375
0
      recv_proto_id = msg->rcv.bind_address->useinfo.proto;
1376
0
    } else {
1377
0
      recv_proto_id = msg->rcv.bind_address->proto;
1378
0
    }
1379
0
  }
1380
1381
0
  orig = msg->buf;
1382
0
  offset = *new_buf_offs;
1383
0
  s_offset = *orig_offs;
1384
1385
0
  for(t = lumps; t; t = t->next) {
1386
0
    switch(t->op) {
1387
0
      case LUMP_ADD:
1388
0
      case LUMP_ADD_SUBST:
1389
0
      case LUMP_ADD_OPT:
1390
        /* skip if this is an OPT lump and the condition is
1391
         * not satisfied */
1392
0
        if((t->op == LUMP_ADD_OPT)
1393
0
            && (!lump_check_opt(t, msg, send_info)))
1394
0
          continue;
1395
        /* just add it here! */
1396
        /* process before  */
1397
0
        for(r = t->before; r; r = r->before) {
1398
0
          switch(r->op) {
1399
0
            case LUMP_ADD:
1400
              /*just add it here*/
1401
0
              memcpy(new_buf + offset, r->u.value, r->len);
1402
0
              offset += r->len;
1403
0
              break;
1404
0
            case LUMP_ADD_SUBST:
1405
0
              SUBST_LUMP(r);
1406
0
              break;
1407
0
            case LUMP_ADD_OPT:
1408
              /* skip if this is an OPT lump and the condition is
1409
              * not satisfied */
1410
0
              if(!lump_check_opt(r, msg, send_info))
1411
0
                goto skip_before;
1412
0
              break;
1413
0
            default:
1414
              /* only ADD allowed for before/after */
1415
0
              LM_CRIT("invalid op for data lump (%x)\n", r->op);
1416
0
          }
1417
0
        }
1418
0
      skip_before:
1419
        /* copy "main" part */
1420
0
        switch(t->op) {
1421
0
          case LUMP_ADD:
1422
0
            memcpy(new_buf + offset, t->u.value, t->len);
1423
0
            offset += t->len;
1424
0
            break;
1425
0
          case LUMP_ADD_SUBST:
1426
0
            SUBST_LUMP(t);
1427
0
            break;
1428
0
          case LUMP_ADD_OPT:
1429
            /* do nothing, it's only a condition */
1430
0
            break;
1431
0
          default:
1432
            /* should not ever get here */
1433
0
            LM_CRIT("unhandled data lump op %d\n", t->op);
1434
0
        }
1435
        /* process after */
1436
0
        for(r = t->after; r; r = r->after) {
1437
0
          switch(r->op) {
1438
0
            case LUMP_ADD:
1439
              /*just add it here*/
1440
0
              memcpy(new_buf + offset, r->u.value, r->len);
1441
0
              offset += r->len;
1442
0
              break;
1443
0
            case LUMP_ADD_SUBST:
1444
0
              SUBST_LUMP(r);
1445
0
              break;
1446
0
            case LUMP_ADD_OPT:
1447
              /* skip if this is an OPT lump and the condition is
1448
              * not satisfied */
1449
0
              if(!lump_check_opt(r, msg, send_info))
1450
0
                goto skip_after;
1451
0
              break;
1452
0
            default:
1453
              /* only ADD allowed for before/after */
1454
0
              LM_CRIT("invalid op for data lump (%x)\n", r->op);
1455
0
          }
1456
0
        }
1457
0
      skip_after:
1458
0
        break;
1459
0
      case LUMP_NOP:
1460
0
      case LUMP_DEL:
1461
        /* copy till offset */
1462
0
        if(s_offset > t->u.offset) {
1463
0
          LM_DBG("WARNING: (%d) overlapped lumps offsets,"
1464
0
               " ignoring(%x, %x)\n",
1465
0
              t->op, s_offset, t->u.offset);
1466
          /* this should've been fixed above (when computing len) */
1467
          /* just ignore it*/
1468
0
          break;
1469
0
        }
1470
0
        size = t->u.offset - s_offset;
1471
0
        if(size > 0 && flag == FLAG_MSG_ALL) {
1472
0
          memcpy(new_buf + offset, orig + s_offset, size);
1473
0
          offset += size;
1474
0
          s_offset += size;
1475
0
        } else if(flag == FLAG_MSG_LUMPS_ONLY) {
1476
          /* do not copy the whole message, jump to the lumps offs */
1477
0
          s_offset += size;
1478
0
        }
1479
1480
        /* the LUMP_DELs are printed with "- " before them */
1481
0
        if(t->op == LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) {
1482
0
          new_buf[offset++] = '-';
1483
0
          new_buf[offset++] = ' ';
1484
0
        }
1485
1486
        /* process before  */
1487
0
        for(r = t->before; r; r = r->before) {
1488
0
          switch(r->op) {
1489
0
            case LUMP_ADD:
1490
              /*just add it here*/
1491
0
              memcpy(new_buf + offset, r->u.value, r->len);
1492
0
              offset += r->len;
1493
0
              break;
1494
0
            case LUMP_ADD_SUBST:
1495
0
              SUBST_LUMP(r);
1496
0
              break;
1497
0
            case LUMP_ADD_OPT:
1498
              /* skip if this is an OPT lump and the condition is
1499
              * not satisfied */
1500
0
              if(!lump_check_opt(r, msg, send_info))
1501
0
                goto skip_nop_before;
1502
0
              break;
1503
0
            default:
1504
              /* only ADD allowed for before/after */
1505
0
              LM_CRIT("invalid op for data lump (%x)\n", r->op);
1506
0
          }
1507
0
        }
1508
0
      skip_nop_before:
1509
        /* process main (del only) */
1510
0
        if(t->op == LUMP_DEL && flag == FLAG_MSG_ALL) {
1511
          /* skip len bytes from orig msg */
1512
0
          s_offset += t->len;
1513
0
        } else if(t->op == LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) {
1514
          /* copy lump value and indent as necessarily */
1515
0
          memcpy(new_buf + offset, orig + t->u.offset, t->len);
1516
0
          offset += t->len;
1517
0
          if(new_buf[offset - 1] != '\n') {
1518
0
            new_buf[offset] = '\n';
1519
0
            offset += 1;
1520
0
          }
1521
          /* skip len bytes from orig msg */
1522
0
          s_offset += t->len;
1523
0
        }
1524
1525
        /* process after */
1526
0
        for(r = t->after; r; r = r->after) {
1527
0
          switch(r->op) {
1528
0
            case LUMP_ADD:
1529
              /*just add it here*/
1530
0
              memcpy(new_buf + offset, r->u.value, r->len);
1531
0
              offset += r->len;
1532
0
              break;
1533
0
            case LUMP_ADD_SUBST:
1534
0
              SUBST_LUMP(r);
1535
0
              break;
1536
0
            case LUMP_ADD_OPT:
1537
              /* skip if this is an OPT lump and the condition is
1538
              * not satisfied */
1539
0
              if(!lump_check_opt(r, msg, send_info))
1540
0
                goto skip_nop_after;
1541
0
              break;
1542
0
            default:
1543
              /* only ADD allowed for before/after */
1544
0
              LM_CRIT("invalid op for data lump (%x)\n", r->op);
1545
0
          }
1546
0
        }
1547
0
      skip_nop_after:
1548
0
        break;
1549
0
      default:
1550
0
        LM_CRIT("unknown op (%x)\n", t->op);
1551
0
    }
1552
0
  }
1553
0
  *new_buf_offs = offset;
1554
0
  *orig_offs = s_offset;
1555
1556
  /* add '\0' to char* lump list to print it smoothly */
1557
0
  if(flag == FLAG_MSG_LUMPS_ONLY) {
1558
0
    new_buf[offset] = '\0';
1559
0
  }
1560
0
#undef RCVCOMP_PARAM_ADD
1561
0
#undef SENDCOMP_PARAM_ADD
1562
0
}
1563
1564
1565
/*
1566
 * Adjust/insert Content-Length if necessary
1567
 */
1568
static inline int adjust_clen(struct sip_msg *msg, int body_delta, int proto)
1569
0
{
1570
0
  struct lump *anchor;
1571
0
  char *clen_buf;
1572
0
  int clen_len, body_only;
1573
0
#ifdef USE_TCP
1574
0
  char *body;
1575
0
  int comp_clen;
1576
0
#endif /* USE_TCP */
1577
1578
  /* Calculate message length difference caused by lumps modifying message
1579
   * body, from this point on the message body must not be modified. Zero
1580
   * value indicates that the body hasn't been modified
1581
  */
1582
1583
0
  clen_buf = 0;
1584
0
  anchor = 0;
1585
0
  body_only = 1;
1586
1587
  /* check to see if we need to add clen */
1588
0
#ifdef USE_TCP
1589
0
  if(proto == PROTO_TCP
1590
0
#ifdef USE_TLS
1591
0
      || proto == PROTO_TLS
1592
0
#endif
1593
0
  ) {
1594
0
    if(parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) {
1595
0
      LM_ERR("error parsing content-length\n");
1596
0
      goto error;
1597
0
    }
1598
0
    if(unlikely(msg->content_length == 0)) {
1599
      /* not present, we need to add it */
1600
      /* msg->unparsed should point just before the final crlf
1601
       * - whole message was parsed by the above parse_headers
1602
       *   which did not find content-length */
1603
0
      anchor = anchor_lump(
1604
0
          msg, msg->unparsed - msg->buf, 0, HDR_CONTENTLENGTH_T);
1605
0
      if(anchor == 0) {
1606
0
        LM_ERR("cannot set clen anchor\n");
1607
0
        goto error;
1608
0
      }
1609
0
      body_only = 0;
1610
0
    } else {
1611
      /* compute current content length and compare it with the
1612
         one in the message */
1613
0
      body = get_body(msg);
1614
0
      if(unlikely(body == 0)) {
1615
0
        ser_error = E_BAD_REQ;
1616
0
        LM_ERR("no message body found (missing crlf?)");
1617
0
        goto error;
1618
0
      }
1619
0
      comp_clen = msg->len - (int)(body - msg->buf) + body_delta;
1620
0
      if(comp_clen != (int)(long)msg->content_length->parsed) {
1621
        /* note: we don't distinguish here between received with
1622
           wrong content-length and content-length changed, we just
1623
           fix it automatically in both cases (the reason being
1624
           that an error message telling we have received a msg-
1625
           with wrong content-length is of very little use) */
1626
0
        anchor = del_lump(msg, msg->content_length->body.s - msg->buf,
1627
0
            msg->content_length->body.len, HDR_CONTENTLENGTH_T);
1628
0
        if(anchor == 0) {
1629
0
          LM_ERR("Can't remove original Content-Length\n");
1630
0
          goto error;
1631
0
        }
1632
0
        body_only = 1;
1633
0
      }
1634
0
    }
1635
0
  } else
1636
0
#endif /* USE_TCP */
1637
0
    if(body_delta) {
1638
0
      if(parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) {
1639
0
        LM_ERR("Error parsing Content-Length\n");
1640
0
        goto error;
1641
0
      }
1642
1643
      /* The body has been changed, try to find
1644
     * existing Content-Length
1645
     */
1646
      /* no need for Content-Length if it's an UDP packet and
1647
     * it hasn't Content-Length already */
1648
0
      if(msg->content_length == 0) {
1649
        /* content-length doesn't exist, append it */
1650
        /* msg->unparsed should point just before the final crlf
1651
       * - whole message was parsed by the above parse_headers
1652
       *   which did not find content-length */
1653
0
        if(proto != PROTO_UDP) {
1654
0
          anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0,
1655
0
              HDR_CONTENTLENGTH_T);
1656
0
          if(anchor == 0) {
1657
0
            LM_ERR("cannot set clen anchor\n");
1658
0
            goto error;
1659
0
          }
1660
0
          body_only = 0;
1661
0
        } /* else
1662
        LM_DBG("UDP packet with no clen => not adding one \n"); */
1663
0
      } else {
1664
        /* Content-Length has been found, remove it */
1665
0
        anchor = del_lump(msg, msg->content_length->body.s - msg->buf,
1666
0
            msg->content_length->body.len, HDR_CONTENTLENGTH_T);
1667
0
        if(anchor == 0) {
1668
0
          LM_ERR("Can't remove original Content-Length\n");
1669
0
          goto error;
1670
0
        }
1671
0
      }
1672
0
    }
1673
1674
0
  if(anchor) {
1675
0
    clen_buf = clen_builder(msg, &clen_len, body_delta, body_only);
1676
0
    if(!clen_buf)
1677
0
      goto error;
1678
0
    if(insert_new_lump_after(
1679
0
           anchor, clen_buf, clen_len, HDR_CONTENTLENGTH_T)
1680
0
        == 0)
1681
0
      goto error;
1682
0
  }
1683
1684
0
  return 0;
1685
0
error:
1686
0
  if(clen_buf)
1687
0
    pkg_free(clen_buf);
1688
0
  return -1;
1689
0
}
1690
1691
static inline int find_line_start(
1692
    char *text, unsigned int text_len, char **buf, unsigned int *buf_len)
1693
0
{
1694
0
  char *ch, *start;
1695
0
  unsigned int len;
1696
1697
0
  start = *buf;
1698
0
  len = *buf_len;
1699
1700
0
  while(text_len <= len) {
1701
0
    if(strncmp(text, start, text_len) == 0) {
1702
0
      *buf = start;
1703
0
      *buf_len = len;
1704
0
      return 1;
1705
0
    }
1706
0
    if((ch = memchr(start, 13, len - 1))) {
1707
0
      if(*(ch + 1) != 10) {
1708
0
        LM_ERR("No LF after CR\n");
1709
0
        return 0;
1710
0
      }
1711
0
      len = len - (ch - start + 2);
1712
0
      start = ch + 2;
1713
0
    } else {
1714
0
      LM_ERR("No CRLF found\n");
1715
0
      return 0;
1716
0
    }
1717
0
  }
1718
0
  return 0;
1719
0
}
1720
1721
static inline int get_line(str s)
1722
0
{
1723
0
  char *ch;
1724
1725
0
  if((ch = memchr(s.s, 13, s.len))) {
1726
0
    if(*(ch + 1) != 10) {
1727
0
      LM_ERR("No LF after CR\n");
1728
0
      return 0;
1729
0
    }
1730
0
    return ch - s.s + 2;
1731
0
  } else {
1732
0
    LM_ERR("No CRLF found\n");
1733
0
    return s.len;
1734
0
  }
1735
0
  return 0;
1736
0
}
1737
1738
int replace_body(struct sip_msg *msg, str txt)
1739
0
{
1740
0
  struct lump *anchor;
1741
0
  char *buf;
1742
0
  str body = {0, 0};
1743
1744
0
  body.s = get_body(msg);
1745
0
  if(body.s == 0) {
1746
0
    LM_ERR("malformed sip message\n");
1747
0
    return 0;
1748
0
  }
1749
0
  body.len = msg->len - (int)(body.s - msg->buf);
1750
0
  LM_DBG("old size body[%d] actual[%d]\n", body.len, txt.len);
1751
0
  if(body.s + body.len > msg->buf + msg->len) {
1752
0
    LM_ERR("invalid content length: %d\n", body.len);
1753
0
    return 0;
1754
0
  }
1755
0
  del_nonshm_lump(&(msg->body_lumps));
1756
0
  msg->body_lumps = NULL;
1757
1758
0
  if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0) {
1759
0
    LM_ERR("cannot delete existing body");
1760
0
    return 0;
1761
0
  }
1762
1763
0
  anchor = anchor_lump(msg, body.s - msg->buf, 0, 0);
1764
0
  if(anchor == 0) {
1765
0
    LM_ERR("failed to get anchor\n");
1766
0
    return 0;
1767
0
  }
1768
1769
0
  buf = pkg_malloc(sizeof(char) * txt.len);
1770
0
  if(buf == 0) {
1771
0
    PKG_MEM_ERROR;
1772
0
    return 0;
1773
0
  }
1774
0
  memcpy(buf, txt.s, txt.len);
1775
0
  if(insert_new_lump_after(anchor, buf, txt.len, 0) == 0) {
1776
0
    LM_ERR("failed to insert body lump\n");
1777
0
    pkg_free(buf);
1778
0
    return 0;
1779
0
  }
1780
0
  return 1;
1781
0
}
1782
1783
/**
1784
 * returns the boundary defined by the Content-Type
1785
 * header
1786
 */
1787
int get_boundary(struct sip_msg *msg, str *boundary)
1788
0
{
1789
0
  str params;
1790
0
  param_t *p, *list;
1791
0
  param_hooks_t hooks;
1792
1793
0
  params.s =
1794
0
      memchr(msg->content_type->body.s, ';', msg->content_type->body.len);
1795
0
  if(params.s == NULL) {
1796
0
    LM_INFO("Content-Type hdr has no boundary params <%.*s>\n",
1797
0
        msg->content_type->body.len, msg->content_type->body.s);
1798
0
    return -2;
1799
0
  }
1800
0
  params.len = msg->content_type->body.len
1801
0
         - (params.s - msg->content_type->body.s);
1802
0
  if(parse_params(&params, CLASS_ANY, &hooks, &list) < 0) {
1803
0
    LM_ERR("while parsing Content-Type params\n");
1804
0
    return -1;
1805
0
  }
1806
0
  boundary->s = NULL;
1807
0
  boundary->len = 0;
1808
0
  for(p = list; p; p = p->next) {
1809
0
    if((p->name.len == 8) && (strncasecmp(p->name.s, "boundary", 8) == 0)) {
1810
0
      boundary->s = pkg_malloc(p->body.len + 2);
1811
0
      if(boundary->s == NULL) {
1812
0
        free_params(list);
1813
0
        PKG_MEM_ERROR;
1814
0
        return -1;
1815
0
      }
1816
0
      *(boundary->s) = '-';
1817
0
      *(boundary->s + 1) = '-';
1818
0
      memcpy(boundary->s + 2, p->body.s, p->body.len);
1819
0
      boundary->len = 2 + p->body.len;
1820
0
      LM_DBG("boundary is <%.*s>\n", boundary->len, boundary->s);
1821
0
      break;
1822
0
    }
1823
0
  }
1824
0
  free_params(list);
1825
0
  return 0;
1826
0
}
1827
1828
int check_boundaries(struct sip_msg *msg, struct dest_info *send_info)
1829
0
{
1830
0
  str b = {0, 0};
1831
0
  str fb = {0, 0};
1832
0
  str ob = {0, 0};
1833
0
  str bsuffix = {"\r\n", 2};
1834
0
  str fsuffix = {"--\r\n", 4};
1835
0
  str body = {0, 0};
1836
0
  str buf = {0, 0};
1837
0
  str tmp = {0, 0};
1838
0
  struct str_list *lb = NULL;
1839
0
  struct str_list *lb_t = NULL;
1840
0
  int lb_found = 0;
1841
0
  int t, ret, lb_size;
1842
0
  char *pb;
1843
1844
0
  if(!(msg->msg_flags & FL_BODY_MULTIPART)) {
1845
0
    LM_DBG("no multi-part body\n");
1846
0
    return 0;
1847
0
  } else {
1848
0
    if((t = get_boundary(msg, &ob)) != 0) {
1849
0
      if(t == -2) {
1850
0
        LM_INFO("no boundary - maybe just turning into multipart "
1851
0
            "body\n");
1852
0
        return -2;
1853
0
      }
1854
0
      return -1;
1855
0
    }
1856
0
    buf.s = build_body(msg, (unsigned int *)&buf.len, &ret, send_info);
1857
0
    if(ret) {
1858
0
      LM_ERR("Can't get body\n");
1859
0
      return -1;
1860
0
    }
1861
0
    tmp.s = buf.s;
1862
0
    t = tmp.len = buf.len;
1863
0
    if(str_append(&ob, &bsuffix, &b) != 0) {
1864
0
      LM_ERR("Can't append suffix to boundary\n");
1865
0
      goto error;
1866
0
    }
1867
0
    if(str_append(&ob, &fsuffix, &fb) != 0) {
1868
0
      LM_ERR("Can't append suffix to final boundary\n");
1869
0
      goto error;
1870
0
    }
1871
0
    ret = b.len - 2;
1872
0
    while(t > 0) {
1873
0
      if(find_line_start(b.s, ret, &tmp.s, (unsigned int *)&tmp.len)) {
1874
        /*LM_DBG("found t[%d] tmp.len[%d]:[%.*s]\n",
1875
          t, tmp.len, tmp.len, tmp.s);*/
1876
0
        if(!lb) {
1877
0
          lb = pkg_malloc(sizeof(struct str_list));
1878
0
          if(!lb) {
1879
0
            PKG_MEM_ERROR;
1880
0
            goto error;
1881
0
          }
1882
0
          lb->s.s = tmp.s;
1883
0
          lb->s.len = tmp.len;
1884
0
          lb->next = 0;
1885
0
          lb_t = lb;
1886
0
        } else {
1887
0
          lb_t = append_str_list(tmp.s, tmp.len, &lb_t, &lb_size);
1888
0
        }
1889
0
        lb_found = lb_found + 1;
1890
0
        tmp.s = tmp.s + ret;
1891
0
        t = t - ret;
1892
0
        tmp.len = tmp.len - ret;
1893
0
      } else {
1894
0
        t = 0;
1895
0
      }
1896
0
    }
1897
0
    if(lb_found < 2) {
1898
0
      LM_ERR("found[%d] wrong number of boundaries\n", lb_found);
1899
0
      goto error;
1900
0
    }
1901
    /* adding 2 chars in advance */
1902
0
    body.len = buf.len + 2;
1903
0
    body.s = pkg_malloc(sizeof(char) * body.len);
1904
0
    if(!body.s) {
1905
0
      PKG_MEM_ERROR;
1906
0
      goto error;
1907
0
    }
1908
0
    pb = body.s;
1909
0
    body.len = 0;
1910
0
    lb_t = lb;
1911
0
    while(lb_t) {
1912
0
      tmp.s = lb_t->s.s;
1913
0
      tmp.len = lb_t->s.len;
1914
0
      tmp.len = get_line(lb_t->s);
1915
0
      if(tmp.len != b.len || strncmp(b.s, tmp.s, b.len) != 0) {
1916
0
        LM_DBG("malformed boundary in the middle\n");
1917
0
        memcpy(pb, b.s, b.len);
1918
0
        body.len = body.len + b.len;
1919
0
        pb = pb + b.len;
1920
0
        t = lb_t->next->s.s - (lb_t->s.s + tmp.len);
1921
0
        memcpy(pb, lb_t->s.s + tmp.len, t);
1922
0
        pb = pb + t;
1923
        /*LM_DBG("new chunk[%d][%.*s]\n", t, t, pb-t);*/
1924
0
      } else {
1925
0
        t = lb_t->next->s.s - lb_t->s.s;
1926
0
        memcpy(pb, lb_t->s.s, t);
1927
        /*LM_DBG("copy[%d][%.*s]\n", t, t, pb);*/
1928
0
        pb = pb + t;
1929
0
      }
1930
0
      body.len = body.len + t;
1931
      /*LM_DBG("body[%d][%.*s]\n", body.len, body.len, body.s);*/
1932
0
      lb_t = lb_t->next;
1933
0
      if(!lb_t->next)
1934
0
        lb_t = NULL;
1935
0
    }
1936
    /* last boundary */
1937
0
    tmp.s = lb->s.s;
1938
0
    tmp.len = lb->s.len;
1939
0
    tmp.len = get_line(lb->s);
1940
0
    if(tmp.len != fb.len || strncmp(fb.s, tmp.s, fb.len) != 0) {
1941
0
      LM_DBG("last bondary without -- at the end\n");
1942
0
      memcpy(pb, fb.s, fb.len);
1943
      /*LM_DBG("new chunk[%d][%.*s]\n", fb.len, fb.len, pb);*/
1944
0
      pb = pb + fb.len;
1945
0
      body.len = body.len + fb.len;
1946
0
    } else {
1947
0
      memcpy(pb, lb->s.s, lb->s.len);
1948
0
      pb = pb + lb->s.len;
1949
0
      body.len = body.len + lb->s.len;
1950
      /*LM_DBG("copy[%d][%.*s]\n", lb->s.len, lb->s.len, pb - lb->s.len);*/
1951
0
    }
1952
    /*LM_DBG("body[%d][%.*s] expected[%ld]\n",
1953
      body.len, body.len, body.s, pb-body.s); */
1954
0
    if(!replace_body(msg, body)) {
1955
0
      LM_ERR("Can't replace body\n");
1956
0
      goto error;
1957
0
    }
1958
0
    msg->msg_flags &= ~FL_BODY_MULTIPART;
1959
0
    ret = 1;
1960
0
    goto clean;
1961
0
  }
1962
1963
0
error:
1964
0
  ret = -1;
1965
0
clean:
1966
0
  if(ob.s)
1967
0
    pkg_free(ob.s);
1968
0
  if(b.s)
1969
0
    pkg_free(b.s);
1970
0
  if(fb.s)
1971
0
    pkg_free(fb.s);
1972
0
  if(body.s)
1973
0
    pkg_free(body.s);
1974
0
  if(buf.s)
1975
0
    pkg_free(buf.s);
1976
0
  while(lb) {
1977
0
    lb_t = lb->next;
1978
0
    pkg_free(lb);
1979
0
    lb = lb_t;
1980
0
  }
1981
0
  return ret;
1982
0
}
1983
1984
/** builds a request in memory from another sip request.
1985
  *
1986
  * Side-effects: - it adds lumps to the msg which are _not_ cleaned.
1987
  * The added lumps are HDR_VIA_T (almost always added), HDR_CONTENTLENGTH_T
1988
  * and HDR_ROUTE_T (when a Route: header is added as a result of a non-null
1989
  * msg->path_vec).
1990
  *               - it might change send_info->proto and send_info->send_socket
1991
  *                 if proto fallback is enabled (see below).
1992
  *
1993
  * Uses also global_req_flags ( OR'ed with msg->msg_flags, see send_info
1994
  * below).
1995
  *
1996
  * @param msg  - sip message structure, complete with lumps
1997
  * @param returned_len - result length (filled in)
1998
  * @param send_info  - dest_info structure (value/result), contains where the
1999
  *                     packet will be sent to (it's needed for building a
2000
  *                     correct via, fill RR lumps a.s.o.). If MTU based
2001
  *                     protocol fall-back is enabled (see flags below),
2002
  *                     send_info->proto might be updated with the new
2003
  *                     protocol.
2004
  *                     msg->msg_flags used:
2005
  *                     - FL_TCP_MTU_FB, FL_TLS_MTU_FB and FL_SCTP_MTU_FB -
2006
  *                       fallback to the corresp. proto if the built
2007
  *                       message > mtu and send_info->proto==PROTO_UDP.
2008
  *                       It will also update send_info->proto.
2009
  *                     - FL_FORCE_RPORT: add rport to via
2010
  * @param mode - flags for building the message, can be a combination of:
2011
  *                 * BUILD_NO_LOCAL_VIA - don't add a local via
2012
  *                 * BUILD_NO_VIA1_UPDATE - don't update first via (rport,
2013
  *                    received a.s.o)
2014
  *                 * BUILD_NO_PATH - don't add a Route: header with the
2015
  *                   msg->path_vec content.
2016
  *                 * BUILD_IN_SHM - build the result in shm memory
2017
  *
2018
  * @return pointer to the new request (pkg_malloc'ed or shm_malloc'ed,
2019
  * depending on the presence of the BUILD_IN_SHM flag, needs freeing when
2020
  *   done) and sets returned_len or 0 on error.
2021
  */
2022
char *build_req_buf_from_sip_req(struct sip_msg *msg,
2023
    unsigned int *returned_len, struct dest_info *send_info,
2024
    unsigned int mode)
2025
0
{
2026
0
  unsigned int len, new_len, received_len, rport_len, uri_len, via_len,
2027
0
      body_delta;
2028
0
  char *line_buf;
2029
0
  char *received_buf;
2030
0
  char *rport_buf;
2031
0
  char *new_buf;
2032
0
  char *buf;
2033
0
  str path_buf;
2034
0
  unsigned int offset, s_offset, size;
2035
0
  struct lump *via_anchor;
2036
0
  struct lump *via_lump;
2037
0
  struct lump *via_rm;
2038
0
  struct lump *via_insert_param;
2039
0
  struct lump *path_anchor;
2040
0
  struct lump *path_lump;
2041
0
  str branch;
2042
0
  unsigned int flags;
2043
0
  unsigned int udp_mtu;
2044
0
  struct dest_info di;
2045
0
  int ret;
2046
2047
0
  via_insert_param = 0;
2048
0
  uri_len = 0;
2049
0
  buf = msg->buf;
2050
0
  len = msg->len;
2051
0
  received_len = 0;
2052
0
  rport_len = 0;
2053
0
  new_buf = 0;
2054
0
  received_buf = 0;
2055
0
  rport_buf = 0;
2056
0
  via_anchor = 0;
2057
0
  line_buf = 0;
2058
0
  via_len = 0;
2059
0
  path_buf.s = 0;
2060
0
  path_buf.len = 0;
2061
2062
0
  flags = msg->msg_flags | global_req_flags;
2063
0
  if((ret = check_boundaries(msg, send_info)) < 0) {
2064
0
    LM_INFO("check boundaries negative (%d)\n", ret);
2065
0
  }
2066
2067
  /* Calculate message body difference and adjust Content-Length */
2068
0
  body_delta = lumps_len(msg, msg->body_lumps, send_info);
2069
0
  if(adjust_clen(msg, body_delta, send_info->proto) < 0) {
2070
0
    LM_ERR("Error while adjusting Content-Length\n");
2071
0
    goto error00;
2072
0
  }
2073
2074
0
  if(unlikely(mode & BUILD_NO_LOCAL_VIA))
2075
0
    goto after_local_via;
2076
2077
  /* create the via header */
2078
0
  branch.s = msg->add_to_branch_s;
2079
0
  branch.len = msg->add_to_branch_len;
2080
2081
0
  via_anchor = anchor_lump(msg, msg->via1->hdr.s - buf, 0, HDR_VIA_T);
2082
0
  if(unlikely(via_anchor == 0))
2083
0
    goto error00;
2084
0
  line_buf = create_via_hf(&via_len, msg, send_info, &branch);
2085
0
  if(unlikely(!line_buf)) {
2086
0
    LM_ERR("could not create Via header\n");
2087
0
    goto error00;
2088
0
  }
2089
0
  if(unlikely(mode & BUILD_NEW_LOCAL_VIA)) {
2090
    /* delete exiting top Via header */
2091
0
    via_rm = del_lump(
2092
0
        msg, msg->h_via1->name.s - msg->buf, msg->h_via1->len, 0);
2093
0
    if(via_rm == 0) {
2094
0
      LM_ERR("failed to remove exiting Via header\n");
2095
0
      goto error00;
2096
0
    }
2097
    /* do not update old Via header anymore */
2098
0
    mode |= BUILD_NO_VIA1_UPDATE;
2099
0
  }
2100
0
after_local_via:
2101
0
  if(unlikely(mode & BUILD_NO_VIA1_UPDATE))
2102
0
    goto after_update_via1;
2103
  /* check if received needs to be added */
2104
0
  if(received_test(msg)) {
2105
0
    if((received_buf = received_builder(msg, &received_len)) == 0) {
2106
0
      LM_ERR("received_builder failed\n");
2107
0
      goto error00; /* free also line_buf */
2108
0
    }
2109
0
  }
2110
2111
  /* check if rport needs to be updated:
2112
   *  - if FL_FORCE_RPORT is set add it (and del. any previous version)
2113
   *  - if via already contains an rport add it and overwrite the previous
2114
   *  rport value if present (if you don't want to overwrite the previous
2115
   *  version remove the comments) */
2116
0
  if((flags & FL_FORCE_RPORT)
2117
0
      || (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)) {
2118
0
    if((rport_buf = rport_builder(msg, &rport_len)) == 0) {
2119
0
      LM_ERR("rport_builder failed\n");
2120
0
      goto error00; /* free everything */
2121
0
    }
2122
0
  }
2123
2124
  /* find out where the offset of the first parameter that should be added
2125
   * (after host:port), needed by add receive & maybe rport */
2126
0
  if(msg->via1->params.s) {
2127
0
    size = msg->via1->params.s - msg->via1->hdr.s - 1; /*compensate
2128
                              for ';' */
2129
0
  } else {
2130
0
    size = msg->via1->host.s - msg->via1->hdr.s + msg->via1->host.len;
2131
0
    if(msg->via1->port != 0) {
2132
      /*size+=strlen(msg->via1->hdr.s+size+1)+1;*/
2133
0
      size += msg->via1->port_str.len + 1; /* +1 for ':'*/
2134
0
    }
2135
#if 0
2136
      /* no longer necessary, now hots.s contains [] */
2137
      if(send_sock->address.af==AF_INET6) size+=1; /* +1 for ']'*/
2138
#endif
2139
0
  }
2140
  /* if received needs to be added, add anchor after host and add it, or
2141
   * overwrite the previous one if already present */
2142
0
  if(received_buf) {
2143
0
    if(msg->via1->received) { /* received already present => overwrite it*/
2144
0
      via_insert_param =
2145
0
          del_lump(msg, msg->via1->received->start - buf - 1, /*;*/
2146
0
              msg->via1->received->size + 1, /*;*/ HDR_VIA_T);
2147
0
    } else if(via_insert_param == 0) { /* receive not present, ok */
2148
0
      via_insert_param = anchor_lump(
2149
0
          msg, msg->via1->hdr.s - buf + size, 0, HDR_VIA_T);
2150
0
    }
2151
0
    if(via_insert_param == 0)
2152
0
      goto error00; /* free received_buf */
2153
0
    if(insert_new_lump_after(
2154
0
           via_insert_param, received_buf, received_len, HDR_VIA_T)
2155
0
        == 0) {
2156
0
      goto error00; /* free received_buf */
2157
0
    }
2158
0
    received_buf = NULL;
2159
0
  }
2160
  /* if rport needs to be updated, delete it if present and add its value */
2161
0
  if(rport_buf) {
2162
0
    if(msg->via1->rport) { /* rport already present */
2163
0
      via_insert_param =
2164
0
          del_lump(msg, msg->via1->rport->start - buf - 1, /*';'*/
2165
0
              msg->via1->rport->size + 1 /* ; */, HDR_VIA_T);
2166
0
    } else if(via_insert_param == 0) { /*force rport, no rport present */
2167
      /* no rport, add it */
2168
0
      via_insert_param = anchor_lump(
2169
0
          msg, msg->via1->hdr.s - buf + size, 0, HDR_VIA_T);
2170
0
    }
2171
0
    if(via_insert_param == 0)
2172
0
      goto error00; /* free rport_buf */
2173
0
    if(insert_new_lump_after(
2174
0
           via_insert_param, rport_buf, rport_len, HDR_VIA_T)
2175
0
        == 0) {
2176
0
      goto error00; /* free rport_buf */
2177
0
    }
2178
0
    rport_buf = NULL;
2179
0
  }
2180
2181
0
after_update_via1:
2182
  /* add route with path content */
2183
0
  if(unlikely(!(mode & BUILD_NO_PATH) && msg->path_vec.s
2184
0
        && msg->path_vec.len)) {
2185
0
    path_buf.len = ROUTE_PREFIX_LEN + msg->path_vec.len + CRLF_LEN;
2186
0
    path_buf.s = pkg_malloc(path_buf.len + 1);
2187
0
    if(unlikely(path_buf.s == 0)) {
2188
0
      PKG_MEM_ERROR;
2189
0
      ser_error = E_OUT_OF_MEM;
2190
0
      goto error00;
2191
0
    }
2192
0
    memcpy(path_buf.s, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
2193
0
    memcpy(path_buf.s + ROUTE_PREFIX_LEN, msg->path_vec.s,
2194
0
        msg->path_vec.len);
2195
0
    memcpy(path_buf.s + ROUTE_PREFIX_LEN + msg->path_vec.len, CRLF,
2196
0
        CRLF_LEN);
2197
0
    path_buf.s[path_buf.len] = 0;
2198
    /* insert Route header either before the other routes
2199
       (if present & parsed), after the local via or after in front of
2200
        the first via if we don't add a local via*/
2201
0
    if(msg->route) {
2202
0
      path_anchor =
2203
0
          anchor_lump(msg, msg->route->name.s - buf, 0, HDR_ROUTE_T);
2204
0
    } else if(likely(via_anchor)) {
2205
0
      path_anchor = via_anchor;
2206
0
    } else if(likely(msg->via1)) {
2207
0
      path_anchor =
2208
0
          anchor_lump(msg, msg->via1->hdr.s - buf, 0, HDR_ROUTE_T);
2209
0
    } else {
2210
      /* if no via1 (theoretically possible for non-sip messages,
2211
         e.g. http xmlrpc) */
2212
0
      path_anchor = anchor_lump(
2213
0
          msg, msg->headers->name.s - buf, 0, HDR_ROUTE_T);
2214
0
    }
2215
0
    if(unlikely(path_anchor == 0))
2216
0
      goto error00;
2217
0
    if(unlikely((path_lump = insert_new_lump_after(path_anchor, path_buf.s,
2218
0
               path_buf.len, HDR_ROUTE_T))
2219
0
          == 0)) {
2220
0
      goto error00;
2221
0
    }
2222
0
    path_buf.s = NULL;
2223
0
  }
2224
  /* compute new msg len and fix overlapping zones*/
2225
0
  new_len =
2226
0
      len + body_delta + lumps_len(msg, msg->add_rm, send_info) + via_len;
2227
#ifdef XL_DEBUG
2228
  LM_ERR("new_len(%d)=len(%d)+lumps_len\n", new_len, len);
2229
#endif
2230
0
  udp_mtu = cfg_get(core, core_cfg, udp_mtu);
2231
0
  di.proto = PROTO_NONE;
2232
0
  if(unlikely((send_info->proto == PROTO_UDP) && udp_mtu
2233
0
        && (flags & FL_MTU_FB_MASK) && (new_len > udp_mtu)
2234
0
        && (!(mode & BUILD_NO_LOCAL_VIA)))) {
2235
2236
0
    di = *send_info; /* copy whole struct - will be used in the Via builder */
2237
0
    di.proto = PROTO_NONE; /* except the proto */
2238
0
#ifdef USE_TCP
2239
0
    if(!tcp_disable && (flags & FL_MTU_TCP_FB)
2240
0
        && (di.send_sock = get_send_socket(
2241
0
              msg, &send_info->to, PROTO_TCP))) {
2242
0
      di.proto = PROTO_TCP;
2243
0
    }
2244
0
#ifdef USE_TLS
2245
0
    else if(!tls_disable && (flags & FL_MTU_TLS_FB)
2246
0
        && (di.send_sock = get_send_socket(
2247
0
              msg, &send_info->to, PROTO_TLS))) {
2248
0
      di.proto = PROTO_TLS;
2249
0
    }
2250
0
#endif /* USE_TLS */
2251
0
#endif /* USE_TCP */
2252
0
#ifdef USE_SCTP
2253
0
#ifdef USE_TCP
2254
0
    else
2255
0
#endif /* USE_TCP */
2256
0
      if(!sctp_disable && (flags & FL_MTU_SCTP_FB)
2257
0
          && (di.send_sock = get_send_socket(
2258
0
                msg, &send_info->to, PROTO_SCTP))) {
2259
0
        di.proto = PROTO_SCTP;
2260
0
      }
2261
0
#endif /* USE_SCTP */
2262
2263
0
    if(di.proto != PROTO_NONE) {
2264
0
      new_len -= via_len;
2265
0
      if(likely(line_buf))
2266
0
        pkg_free(line_buf);
2267
0
      line_buf = create_via_hf(&via_len, msg, &di, &branch);
2268
0
      if(!line_buf) {
2269
0
        LM_ERR("memory allocation failure!\n");
2270
0
        goto error00;
2271
0
      }
2272
0
      new_len += via_len;
2273
0
    }
2274
0
  }
2275
  /* add via header to the list */
2276
  /* try to add it before msg. 1st via */
2277
  /* add first via, as an anchor for second via*/
2278
0
  if(likely(line_buf)) {
2279
0
    if((via_lump = insert_new_lump_before(
2280
0
          via_anchor, line_buf, via_len, HDR_VIA_T))
2281
0
        == 0) {
2282
0
      goto error00;
2283
0
    }
2284
0
    line_buf = 0;
2285
0
  }
2286
0
  if(msg->new_uri.s) {
2287
0
    uri_len = msg->new_uri.len;
2288
0
    new_len = new_len - msg->first_line.u.request.uri.len + uri_len;
2289
0
  }
2290
0
  if(unlikely(mode & BUILD_IN_SHM))
2291
0
    new_buf = (char *)shm_malloc(new_len + 1);
2292
0
  else
2293
0
    new_buf = (char *)pkg_malloc(new_len + 1);
2294
0
  if(new_buf == 0) {
2295
0
    ser_error = E_OUT_OF_MEM;
2296
0
    if(unlikely(mode & BUILD_IN_SHM)) {
2297
0
      SHM_MEM_ERROR;
2298
0
    } else {
2299
0
      PKG_MEM_ERROR;
2300
0
    }
2301
0
    goto error00;
2302
0
  }
2303
2304
0
  offset = s_offset = 0;
2305
0
  if(msg->new_uri.s) {
2306
    /* copy message up to uri */
2307
0
    size = msg->first_line.u.request.uri.s - buf;
2308
0
    memcpy(new_buf, buf, size);
2309
0
    offset += size;
2310
0
    s_offset += size;
2311
    /* add our uri */
2312
0
    memcpy(new_buf + offset, msg->new_uri.s, uri_len);
2313
0
    offset += uri_len;
2314
0
    s_offset += msg->first_line.u.request.uri.len; /* skip original uri */
2315
0
  }
2316
0
  new_buf[new_len] = 0;
2317
  /* copy msg adding/removing lumps */
2318
0
  process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info,
2319
0
      FLAG_MSG_ALL);
2320
0
  process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info,
2321
0
      FLAG_MSG_ALL);
2322
  /* copy the rest of the message */
2323
0
  memcpy(new_buf + offset, buf + s_offset, len - s_offset);
2324
0
  new_buf[new_len] = 0;
2325
2326
  /* update the send_info if udp_mtu affected */
2327
0
  if(di.proto != PROTO_NONE) {
2328
0
    send_info->proto = di.proto;
2329
0
    send_info->send_sock = di.send_sock;
2330
0
  }
2331
2332
#ifdef DBG_MSG_QA
2333
  if(new_buf[new_len - 1] == 0) {
2334
    LM_ERR("0 in the end\n");
2335
    abort();
2336
  }
2337
#endif
2338
2339
0
  *returned_len = new_len;
2340
0
  return new_buf;
2341
2342
0
error00:
2343
0
  if(received_buf)
2344
0
    pkg_free(received_buf);
2345
0
  if(rport_buf)
2346
0
    pkg_free(rport_buf);
2347
0
  if(path_buf.s)
2348
0
    pkg_free(path_buf.s);
2349
0
  if(line_buf)
2350
0
    pkg_free(line_buf);
2351
2352
0
  *returned_len = 0;
2353
0
  return 0;
2354
0
}
2355
2356
char *generate_res_buf_from_sip_res(
2357
    struct sip_msg *msg, unsigned int *returned_len, unsigned int mode)
2358
0
{
2359
0
  unsigned int new_len, via_len, body_delta;
2360
0
  char *new_buf;
2361
0
  unsigned offset, s_offset, via_offset;
2362
0
  char *buf;
2363
0
  unsigned int len;
2364
0
  str xparams;
2365
0
  sr_lump_t *anchor;
2366
2367
0
  buf = msg->buf;
2368
0
  len = msg->len;
2369
0
  new_buf = 0;
2370
2371
0
  if(unlikely(mode & BUILD_NO_VIA1_UPDATE)) {
2372
0
    via_len = 0;
2373
0
    via_offset = 0;
2374
0
  } else {
2375
    /* we must remove the first via */
2376
0
    if(msg->via1->next) {
2377
0
      via_len = msg->via1->bsize;
2378
0
      via_offset = msg->h_via1->body.s - buf;
2379
0
    } else {
2380
0
      via_len = msg->h_via1->len;
2381
0
      via_offset = msg->h_via1->name.s - buf;
2382
0
    }
2383
0
  }
2384
2385
  /* test and add xavp via reply params */
2386
0
  if(msg && msg->via2 && (msg->msg_flags & FL_ADD_XAVP_VIA_REPLY_PARAMS)
2387
0
      && _ksr_xavp_via_reply_params.len > 0) {
2388
0
    xparams.s = pv_get_buffer();
2389
0
    xparams.len = xavp_serialize_fields_style(&_ksr_xavp_via_reply_params,
2390
0
        1, xparams.s, pv_get_buffer_size());
2391
0
    if(xparams.len > 0) {
2392
0
      LM_DBG("adding via reply xavp params\n");
2393
0
      anchor = anchor_lump(msg,
2394
0
          msg->via2->params.s + msg->via2->params.len - msg->buf, 0,
2395
0
          0);
2396
0
      if(anchor != NULL) {
2397
0
        if(insert_new_lump_after(anchor, xparams.s, xparams.len, 0)
2398
0
            == 0) {
2399
0
          LM_ERR("unable to add via reply xavp params\n");
2400
0
        }
2401
0
      }
2402
0
    }
2403
0
  }
2404
2405
  /* Calculate message body difference and adjust
2406
        * Content-Length
2407
        */
2408
0
  body_delta = lumps_len(msg, msg->body_lumps, 0);
2409
0
  if(adjust_clen(msg, body_delta, (msg->via2 ? msg->via2->proto : PROTO_UDP))
2410
0
      < 0) {
2411
0
    LM_ERR("error while adjusting Content-Length\n");
2412
0
    goto error;
2413
0
  }
2414
2415
0
  if(likely(!(mode & BUILD_NO_VIA1_UPDATE))) {
2416
    /* remove the first via*/
2417
0
    if(del_lump(msg, via_offset, via_len, HDR_VIA_T) == 0) {
2418
0
      LM_ERR("error trying to remove first via\n");
2419
0
      goto error;
2420
0
    }
2421
0
  }
2422
2423
  /* note: unknow the send sock */
2424
0
  new_len = len + body_delta + lumps_len(msg, msg->add_rm, 0);
2425
2426
0
  LM_DBG("old size: %d, new size: %d\n", len, new_len);
2427
0
  new_buf = (char *)pkg_malloc(new_len + 1); /* +1 is for debugging
2428
                       (\0 to print it )*/
2429
0
  if(new_buf == 0) {
2430
0
    PKG_MEM_ERROR;
2431
0
    goto error;
2432
0
  }
2433
0
  new_buf[new_len] = 0; /* debug: print the message */
2434
0
  offset = s_offset = 0;
2435
  /* note: no send sock*/
2436
0
  process_lumps(
2437
0
      msg, msg->add_rm, new_buf, &offset, &s_offset, 0, FLAG_MSG_ALL);
2438
0
  process_lumps(
2439
0
      msg, msg->body_lumps, new_buf, &offset, &s_offset, 0, FLAG_MSG_ALL);
2440
  /* copy the rest of the message */
2441
0
  memcpy(new_buf + offset, buf + s_offset, len - s_offset);
2442
  /* send it! */
2443
0
  LM_DBG("copied size: orig:%d, new: %d, rest: %d msg=\n%s\n", s_offset,
2444
0
      offset, len - s_offset, new_buf);
2445
2446
0
  *returned_len = new_len;
2447
0
  return new_buf;
2448
0
error:
2449
0
  *returned_len = 0;
2450
0
  return 0;
2451
0
}
2452
2453
char *build_res_buf_from_sip_res(
2454
    struct sip_msg *msg, unsigned int *returned_len)
2455
0
{
2456
0
  return generate_res_buf_from_sip_res(msg, returned_len, 0);
2457
0
}
2458
2459
char *build_res_buf_from_sip_req(unsigned int code, str *text, str *new_tag,
2460
    struct sip_msg *msg, unsigned int *returned_len, struct bookmark *bmark)
2461
0
{
2462
0
  char *buf, *p;
2463
0
  unsigned int len, foo;
2464
0
  struct hdr_field *hdr;
2465
0
  struct lump_rpl *lump;
2466
0
  struct lump_rpl *body;
2467
0
  int i;
2468
0
  char *received_buf;
2469
0
  unsigned int received_len;
2470
0
  char *rport_buf;
2471
0
  unsigned int rport_len;
2472
0
  char *warning_buf;
2473
0
  unsigned int warning_len;
2474
0
  char *content_len_buf;
2475
0
  unsigned int content_len_len;
2476
0
  char *after_body;
2477
0
  str to_tag;
2478
0
  char *totags;
2479
0
  int httpreq;
2480
0
  char *pvia;
2481
0
  str xparams = STR_NULL;
2482
2483
0
  body = 0;
2484
0
  buf = 0;
2485
0
  received_buf = rport_buf = warning_buf = content_len_buf = 0;
2486
0
  received_len = rport_len = warning_len = content_len_len = 0;
2487
2488
0
  to_tag.s = 0; /* fixes gcc 4.0 warning */
2489
0
  to_tag.len = 0;
2490
2491
  /* force parsing all headers -- we want to return all
2492
  Via's in the reply and they may be scattered down to the
2493
  end of header (non-block Vias are a really poor property
2494
  of SIP :( ) */
2495
0
  if(parse_headers(msg, HDR_EOH_F, 0) == -1) {
2496
0
    LM_ERR("alas, parse_headers failed\n");
2497
0
    goto error00;
2498
0
  }
2499
2500
  /*computes the length of the new response buffer*/
2501
0
  len = 0;
2502
2503
0
  httpreq = IS_HTTP(msg);
2504
2505
  /* check if received needs to be added */
2506
0
  if(received_test(msg)) {
2507
0
    if((received_buf = received_builder(msg, &received_len)) == 0) {
2508
0
      LM_ERR("alas, received_builder failed\n");
2509
0
      goto error00;
2510
0
    }
2511
0
  }
2512
  /* check if rport needs to be updated */
2513
0
  if(((msg->msg_flags | global_req_flags) & FL_FORCE_RPORT)
2514
0
      || (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)) {
2515
0
    if((rport_buf = rport_builder(msg, &rport_len)) == 0) {
2516
0
      LM_ERR("rport_builder failed\n");
2517
0
      goto error01; /* free everything */
2518
0
    }
2519
0
    if(msg->via1->rport)
2520
0
      len -= msg->via1->rport->size + 1; /* include ';' */
2521
0
  }
2522
2523
  /* test and add xavp via reply params */
2524
0
  if((msg->msg_flags & FL_ADD_XAVP_VIA_REPLY_PARAMS)
2525
0
      && _ksr_xavp_via_reply_params.len > 0) {
2526
0
    xparams.s = pv_get_buffer();
2527
0
    xparams.len = xavp_serialize_fields_style(&_ksr_xavp_via_reply_params,
2528
0
        1, xparams.s, pv_get_buffer_size());
2529
0
    if(xparams.len > 0) {
2530
0
      len += xparams.len; /* starting ';' included */
2531
0
    }
2532
0
  }
2533
2534
  /* first line */
2535
0
  len += msg->first_line.u.request.version.len
2536
0
       + 1 /*space*/ + 3 /*code*/ + 1 /*space*/ + text->len
2537
0
       + CRLF_LEN /*new line*/;
2538
  /*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/
2539
0
  for(hdr = msg->headers; hdr; hdr = hdr->next) {
2540
0
    switch(hdr->type) {
2541
0
      case HDR_TO_T:
2542
0
        if(new_tag && new_tag->len) {
2543
0
          to_tag = get_to(msg)->tag_value;
2544
0
          if(to_tag.len && to_tag.s)
2545
0
            len += new_tag->len - to_tag.len;
2546
0
          else
2547
0
            len += new_tag->len + TOTAG_TOKEN_LEN /*";tag="*/;
2548
0
        }
2549
0
        len += hdr->len;
2550
0
        break;
2551
0
      case HDR_VIA_T:
2552
        /* we always add CRLF to via*/
2553
0
        len += (hdr->body.s + hdr->body.len) - hdr->name.s + CRLF_LEN;
2554
0
        if(hdr == msg->h_via1)
2555
0
          len += received_len + rport_len;
2556
0
        break;
2557
0
      case HDR_RECORDROUTE_T:
2558
        /* RR only for 1xx and 2xx replies */
2559
0
        if(code < 180 || code >= 300)
2560
0
          break;
2561
0
      case HDR_FROM_T:
2562
0
      case HDR_CALLID_T:
2563
0
      case HDR_CSEQ_T:
2564
        /* we keep the original termination for these headers*/
2565
0
        len += hdr->len;
2566
0
        break;
2567
0
      default:
2568
          /* do nothing, we are interested only in the above headers */
2569
0
          ;
2570
0
    }
2571
0
  }
2572
  /* lumps length */
2573
0
  for(lump = msg->reply_lump; lump; lump = lump->next) {
2574
0
    len += lump->text.len;
2575
0
    if(lump->flags & LUMP_RPL_BODY)
2576
0
      body = lump;
2577
0
  }
2578
  /* server header */
2579
0
  if(server_signature && server_hdr.len)
2580
0
    len += server_hdr.len + CRLF_LEN;
2581
  /* warning hdr */
2582
0
  if(sip_warning) {
2583
0
    warning_buf = warning_builder(msg, &warning_len);
2584
0
    if(warning_buf)
2585
0
      len += warning_len + CRLF_LEN;
2586
0
    else
2587
0
      LM_WARN("warning skipped -- too big\n");
2588
0
  }
2589
  /* content length hdr */
2590
0
  if(body) {
2591
0
    content_len_buf = int2str(body->text.len, (int *)&content_len_len);
2592
0
    len += CONTENT_LENGTH_LEN + content_len_len + CRLF_LEN;
2593
0
  } else {
2594
0
    len += CONTENT_LENGTH_LEN + 1 /*0*/ + CRLF_LEN;
2595
0
  }
2596
  /* end of message */
2597
0
  len += CRLF_LEN; /*new line*/
2598
2599
  /*allocating mem*/
2600
0
  buf = (char *)pkg_malloc(len + 1);
2601
0
  if(!buf) {
2602
0
    PKG_MEM_ERROR;
2603
0
    goto error01;
2604
0
  }
2605
2606
  /* filling the buffer*/
2607
0
  p = buf;
2608
  /* first line */
2609
0
  memcpy(p, msg->first_line.u.request.version.s,
2610
0
      msg->first_line.u.request.version.len);
2611
0
  p += msg->first_line.u.request.version.len;
2612
0
  *(p++) = ' ';
2613
  /*code*/
2614
0
  for(i = 2, foo = code; i >= 0; i--, foo = foo / 10)
2615
0
    *(p + i) = '0' + foo - (foo / 10) * 10;
2616
0
  p += 3;
2617
0
  *(p++) = ' ';
2618
0
  memcpy(p, text->s, text->len);
2619
0
  p += text->len;
2620
0
  memcpy(p, CRLF, CRLF_LEN);
2621
0
  p += CRLF_LEN;
2622
  /* headers*/
2623
0
  for(hdr = msg->headers; hdr; hdr = hdr->next) {
2624
0
    switch(hdr->type) {
2625
0
      case HDR_VIA_T:
2626
        /* if is HTTP, backup start of Via header in response */
2627
0
        if(unlikely(httpreq))
2628
0
          pvia = p;
2629
0
        if(hdr == msg->h_via1) {
2630
0
          if(rport_buf) {
2631
0
            if(msg->via1->rport) { /* delete the old one */
2632
              /* copy until rport */
2633
0
              append_str_trans(p, hdr->name.s,
2634
0
                  msg->via1->rport->start - hdr->name.s - 1,
2635
0
                  msg);
2636
              /* copy new rport */
2637
0
              append_str(p, rport_buf, rport_len);
2638
              /* copy the rest of the via */
2639
0
              append_str_trans(p,
2640
0
                  msg->via1->rport->start
2641
0
                      + msg->via1->rport->size,
2642
0
                  hdr->body.s + hdr->body.len
2643
0
                      - msg->via1->rport->start
2644
0
                      - msg->via1->rport->size,
2645
0
                  msg);
2646
0
            } else { /* just append the new one */
2647
              /* normal whole via copy */
2648
0
              append_str_trans(p, hdr->name.s,
2649
0
                  (hdr->body.s + hdr->body.len) - hdr->name.s,
2650
0
                  msg);
2651
0
              append_str(p, rport_buf, rport_len);
2652
0
            }
2653
0
          } else {
2654
            /* normal whole via copy */
2655
0
            append_str_trans(p, hdr->name.s,
2656
0
                (hdr->body.s + hdr->body.len) - hdr->name.s,
2657
0
                msg);
2658
0
          }
2659
0
          if(received_buf)
2660
0
            append_str(p, received_buf, received_len);
2661
0
        } else {
2662
          /* normal whole via copy */
2663
0
          append_str_trans(p, hdr->name.s,
2664
0
              (hdr->body.s + hdr->body.len) - hdr->name.s, msg);
2665
0
        }
2666
0
        if(xparams.len > 0) {
2667
0
          append_str(p, xparams.s, xparams.len);
2668
0
        }
2669
0
        append_str(p, CRLF, CRLF_LEN);
2670
        /* if is HTTP, replace Via with Sia
2671
         * - HTTP Via format is different than SIP Via
2672
         */
2673
0
        if(unlikely(httpreq))
2674
0
          *pvia = 'S';
2675
0
        break;
2676
0
      case HDR_RECORDROUTE_T:
2677
        /* RR only for 1xx and 2xx replies */
2678
0
        if(code < 180 || code >= 300)
2679
0
          break;
2680
0
        append_str(p, hdr->name.s, hdr->len);
2681
0
        break;
2682
0
      case HDR_TO_T:
2683
0
        if(new_tag && new_tag->len) {
2684
0
          if(to_tag.len && to_tag.s) { /* replacement */
2685
            /* before to-tag */
2686
0
            append_str(p, hdr->name.s, to_tag.s - hdr->name.s);
2687
            /* to tag replacement */
2688
0
            bmark->to_tag_val.s = p;
2689
0
            bmark->to_tag_val.len = new_tag->len;
2690
0
            append_str(p, new_tag->s, new_tag->len);
2691
            /* the rest after to-tag */
2692
0
            append_str(p, to_tag.s + to_tag.len,
2693
0
                hdr->name.s + hdr->len
2694
0
                    - (to_tag.s + to_tag.len));
2695
0
          } else { /* adding a new to-tag */
2696
0
            after_body = hdr->body.s + hdr->body.len;
2697
0
            append_str(p, hdr->name.s, after_body - hdr->name.s);
2698
0
            append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN);
2699
0
            bmark->to_tag_val.s = p;
2700
0
            bmark->to_tag_val.len = new_tag->len;
2701
0
            append_str(p, new_tag->s, new_tag->len);
2702
0
            append_str(p, after_body,
2703
0
                hdr->name.s + hdr->len - after_body);
2704
0
          }
2705
0
          break;
2706
0
        } /* no new to-tag -- proceed to 1:1 copying  */
2707
0
        totags = ((struct to_body *)(hdr->parsed))->tag_value.s;
2708
0
        if(totags) {
2709
0
          bmark->to_tag_val.s = p + (totags - hdr->name.s);
2710
0
          bmark->to_tag_val.len =
2711
0
              ((struct to_body *)(hdr->parsed))->tag_value.len;
2712
0
        } else {
2713
0
          bmark->to_tag_val.len = 0;
2714
0
          bmark->to_tag_val.s =
2715
0
              p + (hdr->body.s + hdr->body.len - hdr->name.s);
2716
0
        }
2717
        /* no break */
2718
0
      case HDR_FROM_T:
2719
0
      case HDR_CALLID_T:
2720
0
      case HDR_CSEQ_T:
2721
0
        append_str(p, hdr->name.s, hdr->len);
2722
0
        break;
2723
0
      default:
2724
          /* do nothing, we are interested only in the above headers */
2725
0
          ;
2726
0
    } /* end switch */
2727
0
  }   /* end for */
2728
  /* lumps */
2729
0
  for(lump = msg->reply_lump; lump; lump = lump->next)
2730
0
    if(lump->flags & LUMP_RPL_HDR) {
2731
0
      memcpy(p, lump->text.s, lump->text.len);
2732
0
      p += lump->text.len;
2733
0
    }
2734
  /* server header */
2735
0
  if(server_signature && server_hdr.len > 0) {
2736
0
    memcpy(p, server_hdr.s, server_hdr.len);
2737
0
    p += server_hdr.len;
2738
0
    memcpy(p, CRLF, CRLF_LEN);
2739
0
    p += CRLF_LEN;
2740
0
  }
2741
  /* content_length hdr */
2742
0
  if(content_len_len) {
2743
0
    append_str(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
2744
0
    append_str(p, content_len_buf, content_len_len);
2745
0
    append_str(p, CRLF, CRLF_LEN);
2746
0
  } else {
2747
0
    append_str(
2748
0
        p, CONTENT_LENGTH "0" CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN);
2749
0
  }
2750
  /* warning header */
2751
0
  if(warning_buf) {
2752
0
    memcpy(p, warning_buf, warning_len);
2753
0
    p += warning_len;
2754
0
    memcpy(p, CRLF, CRLF_LEN);
2755
0
    p += CRLF_LEN;
2756
0
  }
2757
  /*end of message*/
2758
0
  memcpy(p, CRLF, CRLF_LEN);
2759
0
  p += CRLF_LEN;
2760
  /* body */
2761
0
  if(body) {
2762
0
    memcpy(p, body->text.s, body->text.len);
2763
0
    p += body->text.len;
2764
0
  }
2765
2766
0
  if(len != p - buf)
2767
0
    LM_CRIT("diff len=%d p-buf=%d\n", len, (int)(p - buf));
2768
2769
0
  *(p) = 0;
2770
0
  *returned_len = len;
2771
  /* in req2reply, received_buf is not introduced to lumps and
2772
     needs to be deleted here
2773
  */
2774
0
  if(received_buf)
2775
0
    pkg_free(received_buf);
2776
0
  if(rport_buf)
2777
0
    pkg_free(rport_buf);
2778
0
  return buf;
2779
2780
0
error01:
2781
0
  if(received_buf)
2782
0
    pkg_free(received_buf);
2783
0
  if(rport_buf)
2784
0
    pkg_free(rport_buf);
2785
0
error00:
2786
0
  *returned_len = 0;
2787
0
  return 0;
2788
0
}
2789
2790
2791
/* return number of chars printed or 0 if space exceeded;
2792
   assumes buffer size of at least MAX_BRANCH_PARAM_LEN
2793
 */
2794
int branch_builder(unsigned int hash_index,
2795
    /* only either parameter useful */
2796
    unsigned int label, char *char_v, int branch, char *branch_str,
2797
    int *len)
2798
0
{
2799
2800
0
  char *begin;
2801
0
  int size;
2802
2803
  /* hash id provided ... start with it */
2804
0
  size = MAX_BRANCH_PARAM_LEN;
2805
0
  begin = branch_str;
2806
0
  *len = 0;
2807
2808
0
  memcpy(begin, MCOOKIE, MCOOKIE_LEN);
2809
0
  size -= MCOOKIE_LEN;
2810
0
  begin += MCOOKIE_LEN;
2811
2812
0
  if(int2reverse_hex(&begin, &size, hash_index) == -1)
2813
0
    return 0;
2814
2815
0
  if(size) {
2816
0
    *begin = BRANCH_SEPARATOR;
2817
0
    begin++;
2818
0
    size--;
2819
0
  } else
2820
0
    return 0;
2821
2822
  /* string with request's characteristic value ... use it ... */
2823
0
  if(char_v) {
2824
0
    if(memcpy(begin, char_v, MD5_LEN)) {
2825
0
      begin += MD5_LEN;
2826
0
      size -= MD5_LEN;
2827
0
    } else
2828
0
      return 0;
2829
0
  } else { /* ... use the "label" value otherwise */
2830
0
    if(int2reverse_hex(&begin, &size, label) == -1)
2831
0
      return 0;
2832
0
  }
2833
2834
0
  if(size) {
2835
0
    *begin = BRANCH_SEPARATOR;
2836
0
    begin++;
2837
0
    size--;
2838
0
  } else
2839
0
    return 0;
2840
2841
0
  if(int2reverse_hex(&begin, &size, branch) == -1)
2842
0
    return 0;
2843
2844
0
  *len = MAX_BRANCH_PARAM_LEN - size;
2845
0
  return size;
2846
0
}
2847
2848
2849
/* uses only the send_info->send_socket, send_info->proto, send_info->id and
2850
 * send_info->comp (so that a send_info used for sending can be passed
2851
 * to this function w/o changes and the correct via will be built) */
2852
char *via_builder(unsigned int *len, sip_msg_t *msg,
2853
    struct dest_info *send_info /* where to send the reply */, str *branch,
2854
    str *extra_params, struct hostport *hp)
2855
0
{
2856
0
  unsigned int via_len, extra_len;
2857
0
  char *line_buf;
2858
0
  int max_len;
2859
0
  int via_prefix_len;
2860
0
  str *address_str = NULL; /* address displayed in via */
2861
0
  str *port_str = NULL;  /* port no displayed in via */
2862
0
  struct socket_info *send_sock;
2863
0
  int comp_len, comp_name_len;
2864
#ifdef USE_COMP
2865
  char *comp_name;
2866
#endif /* USE_COMP */
2867
0
  int port;
2868
0
  int proto;
2869
0
  struct ip_addr ip;
2870
0
  union sockaddr_union *from = NULL;
2871
0
  union sockaddr_union local_addr;
2872
0
  struct tcp_connection *con = NULL;
2873
0
  sr_xavp_t *rxavp = NULL;
2874
0
  str xname;
2875
2876
0
  send_sock = send_info->send_sock;
2877
  /* use pre-set address in via, the outbound socket alias or address one */
2878
0
  if(msg && (msg->msg_flags & FL_USE_XAVP_VIA_FIELDS)
2879
0
      && _ksr_xavp_via_fields.len > 0) {
2880
0
    xname.s = "address";
2881
0
    xname.len = 7;
2882
0
    rxavp = xavp_get_child_with_sval(&_ksr_xavp_via_fields, &xname);
2883
0
    if(rxavp != NULL) {
2884
0
      address_str = &rxavp->val.v.s;
2885
0
    }
2886
0
  }
2887
0
  if(address_str == NULL) {
2888
0
    if(hp && hp->host->len)
2889
0
      address_str = hp->host;
2890
0
    else if(send_sock->useinfo.name.len > 0)
2891
0
      address_str = &(send_sock->useinfo.name);
2892
0
    else
2893
0
      address_str = &(send_sock->address_str);
2894
0
  }
2895
0
  if(msg && (msg->msg_flags & FL_USE_XAVP_VIA_FIELDS)
2896
0
      && _ksr_xavp_via_fields.len > 0) {
2897
0
    xname.s = "port";
2898
0
    xname.len = 4;
2899
0
    rxavp = xavp_get_child_with_sval(&_ksr_xavp_via_fields, &xname);
2900
0
    if(rxavp != NULL) {
2901
0
      port_str = &rxavp->val.v.s;
2902
0
    }
2903
0
  }
2904
0
  if(port_str == NULL) {
2905
0
    if(hp && hp->port->len)
2906
0
      port_str = hp->port;
2907
0
    else if(send_sock->useinfo.port_no > 0)
2908
0
      port_str = &(send_sock->useinfo.port_no_str);
2909
0
    else
2910
0
      port_str = &(send_sock->port_no_str);
2911
0
  }
2912
0
  proto = PROTO_NONE;
2913
0
  if(msg && (msg->msg_flags & FL_USE_XAVP_VIA_FIELDS)
2914
0
      && _ksr_xavp_via_fields.len > 0) {
2915
0
    xname.s = "proto";
2916
0
    xname.len = 5;
2917
0
    rxavp = xavp_get_child_with_sval(&_ksr_xavp_via_fields, &xname);
2918
0
    if(rxavp != NULL) {
2919
0
      proto = get_valid_proto_id(&rxavp->val.v.s);
2920
0
    }
2921
0
  }
2922
0
  if(proto == PROTO_NONE) {
2923
0
    if(send_sock->useinfo.proto != PROTO_NONE) {
2924
0
      proto = send_sock->useinfo.proto;
2925
0
    } else {
2926
0
      proto = send_info->proto;
2927
0
    }
2928
0
  }
2929
0
  comp_len = comp_name_len = 0;
2930
#ifdef USE_COMP
2931
  comp_name = 0;
2932
  switch(send_info->comp) {
2933
    case COMP_NONE:
2934
      break;
2935
    case COMP_SIGCOMP:
2936
      comp_len = COMP_PARAM_LEN;
2937
      comp_name_len = SIGCOMP_NAME_LEN;
2938
      comp_name = SIGCOMP_NAME;
2939
      break;
2940
    case COMP_SERGZ:
2941
      comp_len = COMP_PARAM_LEN;
2942
      comp_name_len = SERGZ_NAME_LEN;
2943
      comp_name = SERGZ_NAME;
2944
      break;
2945
    default:
2946
      LM_CRIT("unknown comp %d\n", send_info->comp);
2947
      /* continue, we'll just ignore comp */
2948
  }
2949
#endif /* USE_COMP */
2950
2951
0
  via_prefix_len = MY_VIA_LEN + (proto == PROTO_SCTP);
2952
0
  max_len = via_prefix_len + address_str->len /* space in MY_VIA */
2953
0
        + 2 /* just in case it is a v6 address ... [ ] */
2954
0
        + 1 /*':'*/ + port_str->len
2955
0
        + (branch ? (MY_BRANCH_LEN + branch->len) : 0)
2956
0
        + (extra_params ? extra_params->len : 0) + comp_len
2957
0
        + comp_name_len + CRLF_LEN + 1;
2958
0
  line_buf = pkg_malloc(max_len);
2959
0
  if(line_buf == 0) {
2960
0
    ser_error = E_OUT_OF_MEM;
2961
0
    PKG_MEM_ERROR;
2962
0
    return 0;
2963
0
  }
2964
2965
0
  extra_len = 0;
2966
2967
0
  via_len = via_prefix_len + address_str->len; /*space included in MY_VIA*/
2968
2969
0
  memcpy(line_buf, MY_VIA, MY_VIA_LEN);
2970
0
  if(proto == PROTO_UDP) {
2971
    /* do nothing */
2972
0
  } else if(proto == PROTO_TCP) {
2973
0
    memcpy(line_buf + MY_VIA_LEN - 4, "TCP ", 4);
2974
0
  } else if(proto == PROTO_TLS) {
2975
0
    memcpy(line_buf + MY_VIA_LEN - 4, "TLS ", 4);
2976
0
  } else if(proto == PROTO_SCTP) {
2977
0
    memcpy(line_buf + MY_VIA_LEN - 4, "SCTP ", 5);
2978
0
  } else if(proto == PROTO_WS) {
2979
0
    if(unlikely(send_info->send_flags.f & SND_F_FORCE_SOCKET
2980
0
          && send_info->send_sock)) {
2981
0
      local_addr = send_info->send_sock->su;
2982
0
      su_setport(&local_addr, 0); /* any local port will do */
2983
0
      from = &local_addr;
2984
0
    }
2985
2986
0
    port = su_getport(&send_info->to);
2987
0
    if(likely(port)) {
2988
0
      su2ip_addr(&ip, &send_info->to);
2989
0
      con = tcpconn_get(send_info->id, &ip, port, from, 0);
2990
0
    } else if(likely(send_info->id))
2991
0
      con = tcpconn_get(send_info->id, 0, 0, 0, 0);
2992
0
    else {
2993
0
      LM_CRIT("null_id & to\n");
2994
0
      pkg_free(line_buf);
2995
0
      return 0;
2996
0
    }
2997
2998
0
    if(con == NULL) {
2999
0
      LM_WARN("TCP/TLS connection (id: %d) for WebSocket could not be "
3000
0
          "found\n",
3001
0
          send_info->id);
3002
0
      pkg_free(line_buf);
3003
0
      return 0;
3004
0
    }
3005
3006
0
    if(con->rcv.proto == PROTO_WS) {
3007
0
      memcpy(line_buf + MY_VIA_LEN - 4, "WS ", 3);
3008
0
    } else if(con->rcv.proto == PROTO_WSS) {
3009
0
      memcpy(line_buf + MY_VIA_LEN - 4, "WSS ", 4);
3010
0
    } else {
3011
0
      tcpconn_put(con);
3012
0
      LM_CRIT("unknown proto %d\n", con->rcv.proto);
3013
0
      pkg_free(line_buf);
3014
0
      return 0;
3015
0
    }
3016
0
    tcpconn_put(con);
3017
0
  } else if(proto == PROTO_WSS) {
3018
0
    memcpy(line_buf + MY_VIA_LEN - 4, "WSS ", 4);
3019
0
  } else {
3020
0
    LM_CRIT("unknown proto %d\n", proto);
3021
0
    pkg_free(line_buf);
3022
0
    return 0;
3023
0
  }
3024
  /* add [] only if ipv6 address is used;
3025
   * if using pre-set no check is made */
3026
0
  if(send_sock->address.af == AF_INET6) {
3027
    /* lightweight safety checks if brackets set
3028
     * or non-ipv6 (e.g., advertised hostname) */
3029
0
    if(address_str->s[0] != '['
3030
0
        && memchr(address_str->s, ':', address_str->len) != NULL) {
3031
0
      line_buf[via_prefix_len] = '[';
3032
0
      line_buf[via_prefix_len + 1 + address_str->len] = ']';
3033
0
      extra_len = 1;
3034
0
      via_len += 2; /* [ ]*/
3035
0
    }
3036
0
  }
3037
0
  memcpy(line_buf + via_prefix_len + extra_len, address_str->s,
3038
0
      address_str->len);
3039
0
  if((send_sock->port_no != SIP_PORT)
3040
0
      || (port_str != &send_sock->port_no_str)) {
3041
0
    line_buf[via_len] = ':';
3042
0
    via_len++;
3043
0
    memcpy(line_buf + via_len, port_str->s, port_str->len);
3044
0
    via_len += port_str->len;
3045
0
  }
3046
3047
  /* branch parameter */
3048
0
  if(branch) {
3049
0
    memcpy(line_buf + via_len, MY_BRANCH, MY_BRANCH_LEN);
3050
0
    via_len += MY_BRANCH_LEN;
3051
0
    memcpy(line_buf + via_len, branch->s, branch->len);
3052
0
    via_len += branch->len;
3053
0
  }
3054
  /* extra params  */
3055
0
  if(extra_params) {
3056
0
    memcpy(line_buf + via_len, extra_params->s, extra_params->len);
3057
0
    via_len += extra_params->len;
3058
0
  }
3059
#ifdef USE_COMP
3060
  /* comp */
3061
  if(comp_len) {
3062
    memcpy(line_buf + via_len, COMP_PARAM, COMP_PARAM_LEN);
3063
    via_len += COMP_PARAM_LEN;
3064
    memcpy(line_buf + via_len, comp_name, comp_name_len);
3065
    via_len += comp_name_len;
3066
  }
3067
#endif
3068
3069
0
  memcpy(line_buf + via_len, CRLF, CRLF_LEN);
3070
0
  via_len += CRLF_LEN;
3071
0
  line_buf[via_len] = 0; /* null terminate the string*/
3072
3073
0
  *len = via_len;
3074
0
  return line_buf;
3075
0
}
3076
3077
/* creates a via header honoring the protocol of the incoming socket
3078
 * msg is an optional parameter */
3079
char *create_via_hf(unsigned int *len, struct sip_msg *msg,
3080
    struct dest_info *send_info /* where to send the reply */, str *branch)
3081
0
{
3082
0
  char *via;
3083
0
  str extra_params;
3084
0
  struct hostport hp;
3085
0
  char sbuf[24];
3086
0
  int slen;
3087
0
  str xparams;
3088
0
#if defined USE_TCP || defined USE_SCTP
3089
0
  char *id_buf;
3090
0
  unsigned int id_len;
3091
3092
3093
0
  id_buf = 0;
3094
0
  id_len = 0;
3095
0
#endif
3096
0
  extra_params.len = 0;
3097
0
  extra_params.s = 0;
3098
3099
3100
0
#if defined USE_TCP || defined USE_SCTP
3101
  /* add id if tcp */
3102
0
  if(msg
3103
0
      && (
3104
0
#ifdef USE_TCP
3105
0
          (msg->rcv.proto == PROTO_TCP)
3106
0
#ifdef USE_TLS
3107
0
          || (msg->rcv.proto == PROTO_TLS)
3108
0
#endif
3109
0
#ifdef USE_SCTP
3110
0
          ||
3111
0
#endif /* USE_SCTP */
3112
0
#endif /* USE_TCP */
3113
0
#ifdef USE_SCTP
3114
0
          (msg->rcv.proto == PROTO_SCTP)
3115
0
#endif /* USE_SCTP */
3116
0
              )) {
3117
0
    if((id_buf = id_builder(msg, &id_len)) == 0) {
3118
0
      LM_ERR("id_builder failed\n");
3119
0
      return 0; /* we don't need to free anything,
3120
                       nothing alloc'ed yet*/
3121
0
    }
3122
0
    LM_DBG("id added: <%.*s>, rcv proto=%d\n", (int)id_len, id_buf,
3123
0
        msg->rcv.proto);
3124
0
    extra_params.s = id_buf;
3125
0
    extra_params.len = id_len;
3126
0
  }
3127
0
#endif /* USE_TCP || USE_SCTP */
3128
3129
  /* test and add rport parameter to local via - rfc3581 */
3130
0
  if((ksr_local_rport) || (msg && (msg->msg_flags & FL_ADD_LOCAL_RPORT))) {
3131
    /* params so far + ';rport' + '\0' */
3132
0
    via = (char *)pkg_malloc(extra_params.len + RPORT_LEN);
3133
0
    if(via == 0) {
3134
0
      PKG_MEM_ERROR;
3135
0
      if(extra_params.s)
3136
0
        pkg_free(extra_params.s);
3137
0
      return 0;
3138
0
    }
3139
0
    if(extra_params.s != NULL && extra_params.len > 0) {
3140
0
      memcpy(via, extra_params.s, extra_params.len);
3141
0
    }
3142
0
    if(extra_params.s != NULL) {
3143
0
      pkg_free(extra_params.s);
3144
0
    }
3145
0
    memcpy(via + extra_params.len, RPORT, RPORT_LEN - 1);
3146
0
    extra_params.s = via;
3147
0
    extra_params.len += RPORT_LEN - 1;
3148
0
    extra_params.s[extra_params.len] = '\0';
3149
0
  }
3150
3151
  /* test and add srvid parameter to local via  */
3152
0
  if(msg && (msg->msg_flags & FL_ADD_SRVID) && server_id != 0) {
3153
0
    slen = snprintf(sbuf, 24, ";srvid=%u", (unsigned int)server_id);
3154
0
    if(slen <= 0 || slen >= 24) {
3155
0
      LM_WARN("failed to build srvid parameter");
3156
0
    } else {
3157
0
      via = (char *)pkg_malloc(extra_params.len + slen + 1);
3158
0
      if(via == 0) {
3159
0
        PKG_MEM_ERROR;
3160
0
        if(extra_params.s)
3161
0
          pkg_free(extra_params.s);
3162
0
        return 0;
3163
0
      }
3164
0
      if(extra_params.s != NULL && extra_params.len > 0) {
3165
0
        memcpy(via, extra_params.s, extra_params.len);
3166
0
      }
3167
0
      if(extra_params.s != NULL) {
3168
0
        pkg_free(extra_params.s);
3169
0
      }
3170
0
      memcpy(via + extra_params.len, sbuf, slen);
3171
0
      extra_params.s = via;
3172
0
      extra_params.len += slen;
3173
0
      extra_params.s[extra_params.len] = '\0';
3174
0
    }
3175
0
  }
3176
3177
  /* test and add xavp params */
3178
0
  if(msg && (msg->msg_flags & FL_ADD_XAVP_VIA_PARAMS)
3179
0
      && _ksr_xavp_via_params.len > 0) {
3180
0
    xparams.s = pv_get_buffer();
3181
0
    xparams.len = xavp_serialize_fields(
3182
0
        &_ksr_xavp_via_params, xparams.s, pv_get_buffer_size());
3183
0
    if(xparams.len > 0) {
3184
0
      via = (char *)pkg_malloc(extra_params.len + xparams.len + 2);
3185
0
      if(via == 0) {
3186
0
        PKG_MEM_ERROR;
3187
0
        if(extra_params.s)
3188
0
          pkg_free(extra_params.s);
3189
0
        return 0;
3190
0
      }
3191
0
      if(extra_params.s != NULL && extra_params.len > 0) {
3192
0
        memcpy(via, extra_params.s, extra_params.len);
3193
0
      }
3194
0
      if(extra_params.s != NULL) {
3195
0
        pkg_free(extra_params.s);
3196
0
      }
3197
      /* add ';' between via parameters */
3198
0
      via[extra_params.len] = ';';
3199
      /* skip last ';' from xavp serialized output */
3200
0
      memcpy(via + extra_params.len + 1, xparams.s, xparams.len - 1);
3201
0
      extra_params.s = via;
3202
0
      extra_params.len += xparams.len;
3203
0
      extra_params.s[extra_params.len] = '\0';
3204
0
    }
3205
0
  }
3206
3207
0
  set_hostport(&hp, msg);
3208
0
  via = via_builder(len, msg, send_info, branch,
3209
0
      extra_params.len ? &extra_params : 0, &hp);
3210
3211
  /* we do not need extra_params any more, already in the new via header */
3212
0
  if(extra_params.s)
3213
0
    pkg_free(extra_params.s);
3214
0
  return via;
3215
0
}
3216
3217
/* builds a char* buffer from message headers without body
3218
 * first line is excluded in case of skip_first_line=1
3219
 * error is set -1 if the memory allocation fails
3220
 */
3221
char *build_only_headers(struct sip_msg *msg, int skip_first_line,
3222
    unsigned int *returned_len, int *error, struct dest_info *send_info)
3223
0
{
3224
0
  char *buf, *new_buf;
3225
0
  unsigned int offset, s_offset, len, new_len;
3226
3227
0
  *error = 0;
3228
0
  buf = msg->buf;
3229
0
  if(skip_first_line)
3230
0
    s_offset = msg->headers->name.s - buf;
3231
0
  else
3232
0
    s_offset = 0;
3233
3234
  /* original length without body, and without final \r\n */
3235
0
  len = msg->unparsed - buf;
3236
  /* new msg length */
3237
0
  new_len = len -                   /* original length  */
3238
0
        s_offset +                /* skipped first line */
3239
0
        lumps_len(msg, msg->add_rm, send_info); /* lumps */
3240
3241
0
  if(new_len == 0) {
3242
0
    *returned_len = 0;
3243
0
    return 0;
3244
0
  }
3245
3246
0
  new_buf = (char *)pkg_malloc(new_len + 1);
3247
0
  if(!new_buf) {
3248
0
    PKG_MEM_ERROR;
3249
0
    *error = -1;
3250
0
    return 0;
3251
0
  }
3252
0
  new_buf[0] = 0;
3253
0
  offset = 0;
3254
3255
  /* copy message lumps */
3256
0
  process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info,
3257
0
      FLAG_MSG_ALL);
3258
  /* copy the rest of the message without body */
3259
0
  if(len > s_offset) {
3260
0
    memcpy(new_buf + offset, buf + s_offset, len - s_offset);
3261
0
    offset += (len - s_offset);
3262
0
  }
3263
0
  new_buf[offset] = 0;
3264
3265
0
  *returned_len = offset;
3266
0
  return new_buf;
3267
0
}
3268
3269
/* builds a char* buffer from message body
3270
 * error is set -1 if the memory allocation fails
3271
 */
3272
char *build_body(struct sip_msg *msg, unsigned int *returned_len, int *error,
3273
    struct dest_info *send_info)
3274
0
{
3275
0
  char *buf, *new_buf, *body;
3276
0
  unsigned int offset, s_offset, len, new_len;
3277
3278
0
  *error = 0;
3279
0
  body = get_body(msg);
3280
3281
0
  if(!body || (body[0] == 0)) {
3282
0
    *returned_len = 0;
3283
0
    return 0;
3284
0
  }
3285
0
  buf = msg->buf;
3286
0
  s_offset = body - buf;
3287
3288
  /* original length of msg with body */
3289
0
  len = msg->len;
3290
  /* new body length */
3291
0
  new_len = len -                     /* original length  */
3292
0
        s_offset +                  /* msg without body */
3293
0
        lumps_len(msg, msg->body_lumps, send_info); /* lumps */
3294
3295
0
  new_buf = (char *)pkg_malloc(new_len + 1);
3296
0
  if(!new_buf) {
3297
0
    PKG_MEM_ERROR;
3298
0
    *error = -1;
3299
0
    return 0;
3300
0
  }
3301
0
  new_buf[0] = 0;
3302
0
  offset = 0;
3303
3304
  /* copy body lumps */
3305
0
  process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info,
3306
0
      FLAG_MSG_ALL);
3307
  /* copy the rest of the message without body */
3308
0
  if(len > s_offset) {
3309
0
    memcpy(new_buf + offset, buf + s_offset, len - s_offset);
3310
0
    offset += (len - s_offset);
3311
0
  }
3312
0
  new_buf[offset] = 0;
3313
3314
0
  *returned_len = offset;
3315
0
  return new_buf;
3316
0
}
3317
3318
/* builds a char* buffer from SIP message including body
3319
 * The function adjusts the Content-Length HF according
3320
 * to body lumps in case of touch_clen=1.
3321
 */
3322
char *build_all(struct sip_msg *msg, int touch_clen, unsigned int *returned_len,
3323
    int *error, struct dest_info *send_info)
3324
0
{
3325
0
  char *buf, *new_buf;
3326
0
  unsigned int offset, s_offset, len, new_len;
3327
0
  unsigned int body_delta;
3328
3329
0
  *error = 0;
3330
  /* Calculate message body difference */
3331
0
  body_delta = lumps_len(msg, msg->body_lumps, send_info);
3332
0
  if(touch_clen) {
3333
    /* adjust Content-Length */
3334
0
    if(adjust_clen(msg, body_delta, send_info->proto) < 0) {
3335
0
      LM_ERR("Error while adjusting Content-Length\n");
3336
0
      *error = -1;
3337
0
      return 0;
3338
0
    }
3339
0
  }
3340
3341
0
  buf = msg->buf;
3342
  /* original msg length */
3343
0
  len = msg->len;
3344
  /* new msg length */
3345
0
  new_len = len +                    /* original length  */
3346
0
        lumps_len(msg, msg->add_rm, send_info) + /* hdr lumps */
3347
0
        body_delta;                /* body lumps */
3348
3349
0
  if(new_len == 0) {
3350
0
    returned_len = 0;
3351
0
    return 0;
3352
0
  }
3353
3354
0
  new_buf = (char *)pkg_malloc(new_len + 1);
3355
0
  if(!new_buf) {
3356
0
    PKG_MEM_ERROR;
3357
0
    *error = -1;
3358
0
    return 0;
3359
0
  }
3360
0
  new_buf[0] = 0;
3361
0
  offset = s_offset = 0;
3362
3363
  /* copy message lumps */
3364
0
  process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info,
3365
0
      FLAG_MSG_ALL);
3366
  /* copy body lumps */
3367
0
  process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info,
3368
0
      FLAG_MSG_ALL);
3369
  /* copy the rest of the message */
3370
0
  memcpy(new_buf + offset, buf + s_offset, len - s_offset);
3371
0
  offset += (len - s_offset);
3372
0
  new_buf[offset] = 0;
3373
3374
0
  *returned_len = offset;
3375
0
  return new_buf;
3376
0
}
3377
3378
3379
/**
3380
 * parse buf in msg and fill several fields
3381
 */
3382
int build_sip_msg_from_buf(
3383
    struct sip_msg *msg, char *buf, int len, unsigned int id)
3384
0
{
3385
0
  if(msg == 0 || buf == 0)
3386
0
    return -1;
3387
3388
0
  memset(msg, 0, sizeof(sip_msg_t));
3389
0
  msg->id = id;
3390
0
  msg->pid = my_pid();
3391
0
  msg->buf = buf;
3392
0
  msg->len = len;
3393
0
  if(parse_msg(buf, len, msg) != 0) {
3394
0
    LM_ERR("parsing failed\n");
3395
0
    return -1;
3396
0
  }
3397
0
  msg->set_global_address = default_global_address;
3398
0
  msg->set_global_port = default_global_port;
3399
0
  return 0;
3400
0
}
3401
3402
/**
3403
 *
3404
 */
3405
int sip_msg_update_buffer(sip_msg_t *msg, str *obuf)
3406
0
{
3407
0
  sip_msg_t tmp;
3408
3409
0
  if(obuf == NULL || obuf->s == NULL || obuf->len <= 0) {
3410
0
    LM_ERR("invalid buffer parameter\n");
3411
0
    return -1;
3412
0
  }
3413
0
#ifdef USE_TCP
3414
0
  if(tcp_get_clone_rcvbuf() == 0) {
3415
0
    LM_ERR("tcp clone received buffer not enabled\n");
3416
0
    return -1;
3417
0
  }
3418
0
#endif
3419
0
  if(obuf->len >= BUF_SIZE) {
3420
0
    LM_ERR("new buffer is too large (%d)\n", obuf->len);
3421
0
    return -1;
3422
0
  }
3423
  /* temporary copy */
3424
0
  memcpy(&tmp, msg, sizeof(sip_msg_t));
3425
3426
  /* reset dst uri and path vector to avoid freeing - restored later */
3427
0
  if(msg->dst_uri.s != NULL) {
3428
0
    msg->dst_uri.s = NULL;
3429
0
    msg->dst_uri.len = 0;
3430
0
  }
3431
0
  if(msg->path_vec.s != NULL) {
3432
0
    msg->path_vec.s = NULL;
3433
0
    msg->path_vec.len = 0;
3434
0
  }
3435
3436
  /* free old msg structure */
3437
0
  free_sip_msg(msg);
3438
0
  memset(msg, 0, sizeof(sip_msg_t));
3439
3440
  /* restore msg fields */
3441
0
  msg->buf = tmp.buf;
3442
0
  msg->id = tmp.id;
3443
0
  msg->pid = tmp.pid;
3444
0
  msg->rcv = tmp.rcv;
3445
0
  msg->set_global_address = tmp.set_global_address;
3446
0
  msg->set_global_port = tmp.set_global_port;
3447
0
  msg->flags = tmp.flags;
3448
0
  msg->msg_flags = tmp.msg_flags;
3449
0
  memcpy(msg->xflags, tmp.xflags, KSR_XFLAGS_SIZE * sizeof(flag_t));
3450
0
  msg->hash_index = tmp.hash_index;
3451
0
  msg->force_send_socket = tmp.force_send_socket;
3452
0
  msg->fwd_send_flags = tmp.fwd_send_flags;
3453
0
  msg->rpl_send_flags = tmp.rpl_send_flags;
3454
0
  msg->dst_uri = tmp.dst_uri;
3455
0
  msg->path_vec = tmp.path_vec;
3456
3457
0
  memcpy(msg->buf, obuf->s, obuf->len);
3458
0
  msg->len = obuf->len;
3459
0
  msg->buf[msg->len] = '\0';
3460
3461
  /* reparse the message */
3462
0
  LM_DBG("SIP message content updated - reparsing\n");
3463
0
  if(parse_msg(msg->buf, msg->len, msg) != 0) {
3464
0
    LM_ERR("parsing new sip message failed [[%.*s]]\n", msg->len, msg->buf);
3465
    /* exit config execution - sip_msg_t structure is no longer
3466
     * valid/safe for config */
3467
0
    return 0;
3468
0
  }
3469
0
  if(parse_headers(msg, HDR_FROM_F | HDR_TO_F | HDR_CALLID_F | HDR_CSEQ_F, 0)
3470
0
      < 0) {
3471
0
    LM_ERR("parsing main headers of new sip message failed [[%.*s]]\n",
3472
0
        msg->len, msg->buf);
3473
    /* exit config execution - sip_msg_t structure is no longer
3474
     * valid/safe for config */
3475
0
    return 0;
3476
0
  }
3477
0
  return 1;
3478
0
}
3479
3480
/**
3481
 *
3482
 */
3483
int sip_msg_apply_changes(sip_msg_t *msg)
3484
0
{
3485
0
  int ret;
3486
0
  dest_info_t dst;
3487
0
  str obuf;
3488
3489
0
  if(msg->first_line.type != SIP_REPLY && get_route_type() != REQUEST_ROUTE) {
3490
0
    LM_ERR("invalid usage - not in request route or a reply\n");
3491
0
    return -1;
3492
0
  }
3493
3494
0
  init_dest_info(&dst);
3495
0
  dst.proto = PROTO_UDP;
3496
0
  if(msg->first_line.type == SIP_REPLY) {
3497
0
    obuf.s = generate_res_buf_from_sip_res(
3498
0
        msg, (unsigned int *)&obuf.len, BUILD_NO_VIA1_UPDATE);
3499
0
  } else {
3500
0
    if(msg->msg_flags & FL_RR_ADDED) {
3501
0
      LM_ERR("cannot apply msg changes after adding record-route"
3502
0
           " header - it breaks conditional 2nd header\n");
3503
0
      return -1;
3504
0
    }
3505
0
    obuf.s = build_req_buf_from_sip_req(msg, (unsigned int *)&obuf.len,
3506
0
        &dst,
3507
0
        BUILD_NO_PATH | BUILD_NO_LOCAL_VIA | BUILD_NO_VIA1_UPDATE);
3508
0
  }
3509
0
  if(obuf.s == NULL) {
3510
0
    LM_ERR("couldn't update msg buffer content\n");
3511
0
    return -1;
3512
0
  }
3513
0
  ret = sip_msg_update_buffer(msg, &obuf);
3514
  /* free new buffer - copied in the static buffer from old sip_msg_t */
3515
0
  pkg_free(obuf.s);
3516
3517
0
  return ret;
3518
0
}