Coverage Report

Created: 2023-11-19 07:01

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