Coverage Report

Created: 2025-11-24 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/msg_translator.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2001-2003 FhG Fokus
3
 * Copyright (C) 2006 Andreas Granig <agranig@linguin.org>
4
 *   ( covers insert_path_as_route() )
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * History:
23
 * --------
24
 * 2003-01-20  bug_fix: use of return value of snprintf aligned to C99 (jiri)
25
 * 2003-01-23  added rport patches, contributed by
26
 *              Maxim Sobolev <sobomax@FreeBSD.org> and heavily modified by me
27
 *              (andrei)
28
 * 2003-01-24  added i param to via of outgoing requests (used by tcp),
29
 *              modified via_builder params (andrei)
30
 * 2003-01-27  more rport fixes (make use of new via_param->start)  (andrei)
31
 * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
32
 * 2003-01-29  scratchpad removed (jiri)
33
 * 2003-02-28  scratchpad compatibility abandoned (jiri)
34
 * 2003-03-01  VOICE_MAIL defs removed (jiri)
35
 * 2003-03-06  totags in outgoing replies bookmarked to enable
36
 *             ACK/200 tag matching (andrei)
37
 * 2003-03-18  killed the build_warning snprintf (andrei)
38
 * 2003-03-31  added subst lump support (andrei)
39
 * 2003-04-01  added opt (conditional) lump support (andrei)
40
 * 2003-04-02  added more subst lumps: SUBST_{SND,RCV}_ALL
41
 *              => ip:port;transport=proto (andrei)
42
 * 2003-04-12  added FL_FORCE_RPORT support (andrei)
43
 * 2003-04-13  updated warning builder -- fixed (andrei)
44
 * 2003-07-10  check_via_address knows now how to compare with ipv6 address
45
 *              references (e.g [::1]) (andrei)
46
 *             build_req_fomr_sip_req no longer adds 1 for ipv6 via parameter
47
 *              position calculations ([] are part of host.s now) (andrei)
48
 * 2003-10-02  via+lump dst address/port can be set to preset values (andrei)
49
 * 2003-10-08  receive_test function-alized (jiri)
50
 * 2003-10-20  added body_lump list (sip_msg), adjust_clen (andrei & jan)
51
 * 2003-11-11  type of rpl_lumps replaced by flags (bogdan)
52
 * 2007-02-22  insert_path_as_route() imported from TM as we need it for
53
 *             stateless processing also; contributed by Andreas Granig
54
 *             (bogdan)
55
 */
56
57
/*!
58
 * \file
59
 * \brief Create and translate SIP messages/ message contents
60
 * - \ref ViaSpecialParams
61
 */
62
63
/*! \page ViaSpecialParams Via header special parameters
64
 *
65
 * Via special params:
66
 *
67
 * \section requests Requests:
68
 * - if the address in via is different from the src_ip or an existing
69
 *   received=something is found, received=src_ip is added (and any preexisting
70
 *   received is deleted). received is added as the first via parameter if no
71
 *   receive is previously present or over the old receive.
72
 * - if the original via contains rport / rport=something or msg->msg_flags
73
 *   FL_FORCE_RPORT is set (e.g. script force_rport() cmd) rport=src_port
74
 *   is added (over previous rport / as first via param or after received
75
 *   if no received was present and received is added too)
76
 * \section localreplies Local replies:
77
 *    (see also sl_send_reply)
78
 *  - rport and received are added in mostly the same way as for requests, but
79
 *    in the reverse order (first rport and then received). See also
80
 *    limitations.
81
 *  - the local reply is sent to the message source ip address. The
82
 *    destination port is set to the source port if rport is present or
83
 *    FL_FORCE_RPORT flag is set, to the via port or to
84
 *    the default sip port (5060) if neither rport or via port are present.
85
 * \section normalreplies "Normal" replies:
86
 *  - if received is present the message is sent to the received address else
87
 *    if no port is present (neither a normal via port or rport) a dns srv
88
 *    lookup is performed on the host part and the reply is sent to the
89
 *    resulting ip. If a port is present or the host part is an ip address
90
 *    the dns lookup will be a "normal" one (A or AAAA).
91
 *  - if rport is present, it's value will be used as the destination port
92
 *   (and this will also disable srv lookups)
93
 *  - if no port is present the destination port will be taken from the srv
94
 *    lookup. If the srv lookup fails or is not performed (e.g. ip address
95
 *    in host) the destination port will be set to the default sip port (5060).
96
 *
97
 * \section limitations Known limitations:
98
 * - when locally replying to a message, rport and received will be appended to
99
 *   the via header parameters (for forwarded requests they are inserted at the
100
 *   beginning).
101
 * - a locally generated reply might get two received via parameters if a
102
 *   received is already present in the original message (this should not
103
 *   happen though, but ...)
104
 *
105
*/
106
107
#include <sys/types.h>
108
#include <sys/socket.h>
109
#include <netdb.h>
110
#include <string.h>
111
#include <stdio.h>
112
#include <stdlib.h>
113
114
#include "msg_translator.h"
115
#include "error.h"
116
#include "mem/mem.h"
117
#include "dprint.h"
118
#include "config.h"
119
#include "md5utils.h"
120
#include "data_lump.h"
121
#include "data_lump_rpl.h"
122
#include "ip_addr.h"
123
#include "resolve.h"
124
#include "ut.h"
125
#include "pt.h"
126
#include "context.h"
127
#include "sdp_ops.h"
128
#include "net/trans.h"
129
130
int disable_503_translation = 0;
131
132
#define append_str(_dest,_src,_len) \
133
0
  do{\
134
0
    memcpy( (_dest) , (_src) , (_len) );\
135
0
    (_dest) += (_len) ;\
136
0
  }while(0);
137
138
extern char version[];
139
extern int version_len;
140
141
142
/*! \brief check if IP address in Via != source IP address of signaling */
143
int received_test( struct sip_msg *msg )
144
5.57k
{
145
5.57k
  int rcvd;
146
147
5.57k
  if(msg->via1->received !=NULL)
148
12
    return 1;
149
150
5.56k
  if(msg->via1->maddr){
151
30
    rcvd = check_ip_address(&msg->rcv.src_ip, &msg->via1->maddr->value,
152
30
      msg->via1->port, msg->via1->proto, received_dns);
153
5.53k
  } else {
154
5.53k
    rcvd = check_ip_address(&msg->rcv.src_ip,
155
5.53k
      &msg->via1->host, msg->via1->port, msg->via1->proto, received_dns);
156
5.53k
  }
157
158
5.56k
  return rcvd;
159
5.57k
}
160
161
162
static char * warning_builder( struct sip_msg *msg, unsigned int *returned_len)
163
0
{
164
0
  static char buf[MAX_WARNING_LEN];
165
0
  str *foo;
166
0
  int print_len, l, clen;
167
0
  char* t;
168
169
0
#define str_print(string, string_len) \
170
0
    do{ \
171
0
      l=(string_len); \
172
0
      if ((clen+l)>MAX_WARNING_LEN) \
173
0
        goto error_overflow; \
174
0
      memcpy(buf+clen, (string), l); \
175
0
      clen+=l; \
176
0
    }while(0)
177
178
0
#define str_lenpair_print(string, string_len, string2, string2_len) \
179
0
    do{ \
180
0
      str_print(string, string_len); \
181
0
      str_print(string2, string2_len);\
182
0
    }while(0)
183
184
0
#define str_pair_print( string, string2, string2_len) \
185
0
    str_lenpair_print((string), strlen((string)), (string2), (string2_len))
186
187
0
#define str_int_print(string, intval)\
188
0
    do{\
189
0
      t=int2str((intval), &print_len); \
190
0
      str_pair_print(string, t, print_len);\
191
0
    } while(0)
192
193
0
#define str_ipaddr_print(string, ipaddr_val)\
194
0
    do{\
195
0
      t=ip_addr2a((ipaddr_val)); \
196
0
      print_len=strlen(t); \
197
0
      str_pair_print(string, t, print_len);\
198
0
    } while(0)
199
200
0
  clen=0;
201
0
  str_lenpair_print(WARNING, WARNING_LEN,
202
0
            msg->rcv.bind_address->name.s,
203
0
            msg->rcv.bind_address->name.len);
204
0
  str_lenpair_print(":", 1, msg->rcv.bind_address->port_no_str.s,
205
0
            msg->rcv.bind_address->port_no_str.len);
206
0
  str_print(WARNING_PHRASE, WARNING_PHRASE_LEN);
207
208
  /*adding out_uri*/
209
0
  if (msg->new_uri.s)
210
0
    foo=&(msg->new_uri);
211
0
  else
212
0
    foo=&(msg->first_line.u.request.uri);
213
  /* pid= */
214
0
  str_int_print(" pid=", my_pid());
215
  /* req_src_ip= */
216
0
  str_ipaddr_print(" req_src_ip=", &msg->rcv.src_ip);
217
0
  str_int_print(" req_src_port=", msg->rcv.src_port);
218
0
  str_pair_print(" in_uri=", msg->first_line.u.request.uri.s,
219
0
                msg->first_line.u.request.uri.len);
220
0
  str_pair_print(" out_uri=", foo->s, foo->len);
221
0
  str_pair_print(" via_cnt",
222
0
        (msg->parsed_flag & HDR_EOH_F)==HDR_EOH_F ? "=" : ">", 1);
223
0
  str_int_print("=", via_cnt);
224
0
  if (clen<MAX_WARNING_LEN){ buf[clen]='"'; clen++; }
225
0
  else goto error_overflow;
226
227
228
0
  *returned_len=clen;
229
0
  return buf;
230
0
error_overflow:
231
0
  LM_ERR("buffer size exceeded\n");
232
0
  *returned_len=0;
233
0
  return 0;
234
0
}
235
236
237
238
239
char* received_builder(struct sip_msg *msg, unsigned int *received_len)
240
11.7k
{
241
11.7k
  char *buf, *tmp;
242
11.7k
  int  len, tmp_len;
243
11.7k
  struct ip_addr *source_ip;
244
245
11.7k
  source_ip=&msg->rcv.src_ip;
246
247
11.7k
  buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
248
11.7k
  if (buf==0){
249
0
    ser_error=E_OUT_OF_MEM;
250
0
    LM_ERR("out of pkg memory\n");
251
0
    return 0;
252
0
  }
253
11.7k
  memcpy(buf, RECEIVED, RECEIVED_LEN);
254
11.7k
  if ( (tmp=ip_addr2a(source_ip))==0)
255
0
    return 0; /* error*/
256
11.7k
  tmp_len=strlen(tmp);
257
11.7k
  len=RECEIVED_LEN+tmp_len;
258
259
11.7k
  memcpy(buf+RECEIVED_LEN, tmp, tmp_len);
260
11.7k
  buf[len]=0; /*null terminate it */
261
262
11.7k
  *received_len = len;
263
11.7k
  return buf;
264
11.7k
}
265
266
267
268
char* rport_builder(struct sip_msg *msg, unsigned int *rport_len)
269
6.18k
{
270
6.18k
  char* buf, * tmp;
271
6.18k
  int len, tmp_len;
272
273
6.18k
  tmp_len=0;
274
6.18k
  tmp=int2str(msg->rcv.src_port, &tmp_len);
275
6.18k
  len=RPORT_LEN+tmp_len;
276
6.18k
  buf=pkg_malloc(sizeof(char)*(len+1));/* space for null term */
277
6.18k
  if (buf==0){
278
0
    ser_error=E_OUT_OF_MEM;
279
0
    LM_ERR("out of pkg memory\n");
280
0
    return 0;
281
0
  }
282
6.18k
  memcpy(buf, RPORT, RPORT_LEN);
283
6.18k
  memcpy(buf+RPORT_LEN, tmp, tmp_len);
284
6.18k
  buf[len]=0; /*null terminate it*/
285
286
6.18k
  *rport_len=len;
287
6.18k
  return buf;
288
6.18k
}
289
290
291
292
char* id_builder(struct sip_msg* msg, unsigned int *id_len)
293
0
{
294
0
  char* buf, *p;
295
0
  int len, value_len, size;
296
0
  char revhex[sizeof(int)*2];
297
298
0
  size=sizeof(int)*2;
299
0
  p=&revhex[0];
300
0
  if (int2reverse_hex(&p, &size, msg->rcv.proto_reserved1)==-1){
301
0
    LM_CRIT("not enough space for id\n");
302
0
    return 0;
303
0
  }
304
0
  value_len=p-&revhex[0];
305
0
  len=ID_PARAM_LEN+value_len;
306
0
  buf=pkg_malloc(sizeof(char)*(len+1));/* place for ending \0 */
307
0
  if (buf==0){
308
0
    ser_error=E_OUT_OF_MEM;
309
0
    LM_ERR("out of pkg memory\n");
310
0
    return 0;
311
0
  }
312
0
  memcpy(buf, ID_PARAM, ID_PARAM_LEN);
313
0
  memcpy(buf+ID_PARAM_LEN, revhex, value_len);
314
0
  buf[len]=0; /* null terminate it */
315
0
  *id_len=len;
316
0
  return buf;
317
0
}
318
319
320
321
char* clen_builder(struct sip_msg* msg, int *clen_len, int diff)
322
0
{
323
0
  char *buf, * value_s;
324
0
  int len, value, value_len;
325
0
  str body;
326
327
0
  if ( (get_body(msg,&body)!=0) ) {
328
0
    ser_error=E_BAD_REQ;
329
0
    LM_ERR("no message body found (missing crlf?)");
330
0
    return 0;
331
0
  }
332
333
  /* with SDP ops, the body len is fully known (ignore diff) */
334
0
  value = body.len + (have_sdp_ops(msg) ? 0 : diff);
335
0
  value_s=int2str(value, &value_len);
336
0
  LM_DBG("content-length: %d (%s)\n", value, value_s);
337
338
0
  len=CONTENT_LENGTH_LEN+value_len+CRLF_LEN;
339
0
  buf=pkg_malloc(sizeof(char)*(len+1));
340
0
  if (buf==0){
341
0
    ser_error=E_OUT_OF_MEM;
342
0
    LM_ERR("out of pkg memory\n");
343
0
    return 0;
344
0
  }
345
0
  memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
346
0
  memcpy(buf+CONTENT_LENGTH_LEN, value_s, value_len);
347
0
  memcpy(buf+CONTENT_LENGTH_LEN+value_len, CRLF, CRLF_LEN);
348
0
  buf[len]=0; /* null terminate it */
349
0
  *clen_len=len;
350
0
  return buf;
351
0
}
352
353
354
355
/*! \brief* checks if a lump opt condition
356
 * returns 1 if cond is true, 0 if false */
357
static inline int lump_check_opt( struct lump *l,
358
                  struct sip_msg* msg,
359
                  const struct socket_info* snd_s
360
                  )
361
0
{
362
0
  const struct ip_addr* ip;
363
0
  unsigned short port;
364
0
  int proto;
365
366
0
#define get_ip_port_proto \
367
0
      if (snd_s==0){ \
368
0
        LM_CRIT("null send socket\n"); \
369
0
        return 1; /* we presume they are different :-) */ \
370
0
      } \
371
0
      if (msg->rcv.bind_address){ \
372
0
        ip=&msg->rcv.bind_address->address; \
373
0
        port=msg->rcv.bind_address->port_no; \
374
0
        proto=msg->rcv.bind_address->proto; \
375
0
      }else{ \
376
0
        ip=&msg->rcv.dst_ip; \
377
0
        port=msg->rcv.dst_port; \
378
0
        proto=msg->rcv.proto; \
379
0
      } \
380
0
381
0
  switch(l->u.cond){
382
0
    case COND_FALSE:
383
0
      return 0;
384
0
    case COND_TRUE:
385
0
      l->flags |= LUMPFLAG_COND_TRUE;
386
0
      return 1;
387
0
    case COND_IF_DIFF_REALMS:
388
0
      get_ip_port_proto;
389
      /* faster tests first */
390
0
      if ((port==snd_s->port_no)&&(proto==snd_s->proto)&&
391
0
        (ip_addr_cmp(ip, &snd_s->address))) {
392
0
        l->flags &= ~LUMPFLAG_COND_TRUE;
393
0
        return 0;
394
0
      }
395
0
      l->flags |= LUMPFLAG_COND_TRUE;
396
0
      return 1;
397
0
    case COND_IF_SAME_REALMS:
398
0
      get_ip_port_proto;
399
      /* faster tests first */
400
0
      if ((port!=snd_s->port_no)||(proto!=snd_s->proto)||
401
0
        (!ip_addr_cmp(ip, &snd_s->address))) {
402
0
        l->flags &= ~LUMPFLAG_COND_TRUE;
403
0
        return 0;
404
0
      }
405
0
      l->flags |= LUMPFLAG_COND_TRUE;
406
0
      return 1;
407
0
    case COND_IF_DIFF_AF:
408
0
      get_ip_port_proto;
409
0
      if (ip->af==snd_s->address.af) {
410
0
        l->flags &= ~LUMPFLAG_COND_TRUE;
411
0
        return 0;
412
0
      }
413
0
      l->flags |= LUMPFLAG_COND_TRUE;
414
0
      return 1;
415
0
    case COND_IF_DIFF_PROTO:
416
0
      get_ip_port_proto;
417
0
      if (proto==snd_s->proto) {
418
0
        l->flags &= ~LUMPFLAG_COND_TRUE;
419
0
        return 0;
420
0
      }
421
0
      l->flags |= LUMPFLAG_COND_TRUE;
422
0
      return 1;
423
0
    case COND_IF_DIFF_PORT:
424
0
      get_ip_port_proto;
425
0
      if (port==snd_s->port_no) {
426
0
        l->flags &= ~LUMPFLAG_COND_TRUE;
427
0
        return 0;
428
0
      }
429
0
      l->flags |= LUMPFLAG_COND_TRUE;
430
0
      return 1;
431
0
    case COND_IF_DIFF_IP:
432
0
      get_ip_port_proto;
433
0
      if (ip_addr_cmp(ip, &snd_s->address)) {
434
0
        l->flags &= ~LUMPFLAG_COND_TRUE;
435
0
        return 0;
436
0
      }
437
0
      l->flags |= LUMPFLAG_COND_TRUE;
438
0
      return 1;
439
0
    default:
440
0
      LM_CRIT("unknown lump condition %d\n", l->u.cond);
441
0
  }
442
0
  return 0; /* false */
443
0
}
444
445
446
447
/*! \brief computes the "unpacked" len of a lump list,
448
   code moved from build_req_from_req */
449
static int lumps_len(struct sip_msg* msg, struct lump* lumps,
450
                const struct socket_info* send_sock, int max_offset)
451
23.3k
{
452
23.3k
  unsigned int s_offset, new_len;
453
23.3k
  unsigned int last_del;
454
23.3k
  struct lump *t, *r;
455
23.3k
  const str *send_address_str, *send_port_str;
456
23.3k
  const str *rcv_address_str=NULL;
457
23.3k
  const str *rcv_port_str=NULL;
458
459
23.3k
#define SUBST_LUMP_LEN(subst_l) \
460
23.3k
    switch((subst_l)->u.subst){ \
461
0
      case SUBST_RCV_IP: \
462
0
        if (msg->rcv.bind_address){ \
463
0
          new_len+=rcv_address_str->len; \
464
0
        } else \
465
0
          LM_BUG("null bind address 1"); \
466
0
        break; \
467
0
      case SUBST_RCV_PORT: \
468
0
        if (msg->rcv.bind_address){ \
469
0
          new_len+=rcv_port_str->len; \
470
0
        } else \
471
0
          LM_BUG("null bind address 2"); \
472
0
        break; \
473
0
      case SUBST_RCV_PROTO: \
474
0
        if (msg->rcv.bind_address){ \
475
0
          switch(msg->rcv.bind_address->proto){ \
476
            /* TODO change this to look in proto !*/ \
477
0
            case PROTO_NONE: \
478
0
            case PROTO_UDP: \
479
0
            case PROTO_TCP: \
480
0
            case PROTO_TLS: \
481
0
            case PROTO_WSS: \
482
0
                new_len+=3; \
483
0
                break; \
484
0
            case PROTO_SCTP: \
485
0
                new_len+=4; \
486
0
                break; \
487
0
            case PROTO_WS: \
488
0
                new_len+=2; \
489
0
                break; \
490
0
            default: \
491
0
            LM_CRIT("unknown proto %d\n", \
492
0
                msg->rcv.bind_address->proto); \
493
0
          }\
494
0
        } else \
495
0
          LM_BUG("null bind address 3"); \
496
0
        break; \
497
0
      case SUBST_RCV_ALL: \
498
0
        if (msg->rcv.bind_address){ \
499
0
          new_len+=rcv_address_str->len; \
500
0
          if (msg->rcv.bind_address->port_no!=SIP_PORT || (rcv_port_str!=&(msg->rcv.bind_address->port_no_str))){ \
501
            /* add :port_no */ \
502
0
            new_len+=1+rcv_port_str->len; \
503
0
          }\
504
            /*add;transport=xxx*/ \
505
0
          switch(msg->rcv.bind_address->proto){ \
506
0
            case PROTO_NONE: \
507
0
            case PROTO_UDP: \
508
0
                break; /* udp is the default */ \
509
0
            case PROTO_TCP: \
510
0
            case PROTO_TLS: \
511
0
            case PROTO_WSS: \
512
0
                new_len+=TRANSPORT_PARAM_LEN+3; \
513
0
                break; \
514
0
            case PROTO_SCTP: \
515
0
                new_len+=TRANSPORT_PARAM_LEN+4; \
516
0
                break; \
517
0
            case PROTO_WS: \
518
0
                new_len+=TRANSPORT_PARAM_LEN+2; \
519
0
                break; \
520
0
            default: \
521
0
            LM_CRIT("unknown proto %d\n", \
522
0
                msg->rcv.bind_address->proto); \
523
0
          }\
524
0
        } else \
525
0
          LM_BUG("null bind address 4"); \
526
0
        break; \
527
0
      case SUBST_SND_IP: \
528
0
        if (send_sock){ \
529
0
          new_len+=send_address_str->len; \
530
0
        } else \
531
0
          LM_BUG("null send_socket 1"); \
532
0
        break; \
533
0
      case SUBST_SND_PORT: \
534
0
        if (send_sock){ \
535
0
          new_len+=send_port_str->len; \
536
0
        } else \
537
0
          LM_BUG("null send_socket 2"); \
538
0
        break; \
539
0
      case SUBST_SND_PROTO: \
540
0
        if (send_sock){ \
541
0
          switch(send_sock->proto){ \
542
0
            case PROTO_NONE: \
543
0
            case PROTO_UDP: \
544
0
            case PROTO_TCP: \
545
0
            case PROTO_TLS: \
546
0
            case PROTO_WSS: \
547
0
                new_len+=3; \
548
0
                break; \
549
0
            case PROTO_SCTP: \
550
0
                new_len+=4; \
551
0
                break; \
552
0
            case PROTO_WS: \
553
0
                new_len+=2; \
554
0
                break; \
555
0
            default: \
556
0
            LM_CRIT("unknown proto %d\n", \
557
0
                send_sock->proto); \
558
0
          }\
559
0
        } else \
560
0
          LM_BUG("null send_socket 3"); \
561
0
        break; \
562
0
      case SUBST_SND_ALL: \
563
0
        if (send_sock){ \
564
0
          new_len+=send_address_str->len; \
565
0
          if ((send_sock->port_no!=SIP_PORT) || \
566
0
              (send_port_str!=&(send_sock->port_no_str))){ \
567
            /* add :port_no */ \
568
0
            new_len+=1+send_port_str->len; \
569
0
          }\
570
          /*add;transport=xxx*/ \
571
0
          switch(send_sock->proto){ \
572
0
            case PROTO_NONE: \
573
0
            case PROTO_UDP: \
574
0
                break; /* udp is the default */ \
575
0
            case PROTO_TCP: \
576
0
            case PROTO_TLS: \
577
0
            case PROTO_WSS: \
578
0
                new_len+=TRANSPORT_PARAM_LEN+3; \
579
0
                break; \
580
0
            case PROTO_SCTP: \
581
0
                new_len+=TRANSPORT_PARAM_LEN+4; \
582
0
                break; \
583
0
            case PROTO_WS: \
584
0
                new_len+=TRANSPORT_PARAM_LEN+2; \
585
0
                break; \
586
0
            default: \
587
0
            LM_CRIT("unknown proto %d\n", \
588
0
                send_sock->proto); \
589
0
          }\
590
0
        } else \
591
0
          LM_BUG("null send_socket 4"); \
592
0
        break; \
593
0
      case SUBST_NOP: /* do nothing */ \
594
0
        break; \
595
0
      default: \
596
0
        LM_CRIT("unknown subst type %d\n", \
597
0
            (subst_l)->u.subst); \
598
0
    }
599
600
601
23.3k
  s_offset=0;
602
23.3k
  new_len=0;
603
23.3k
  last_del=0;
604
605
  /* init send_address_str & send_port_str */
606
23.3k
  if(send_sock && send_sock->adv_name_str.len)
607
0
    send_address_str=&(send_sock->adv_name_str);
608
23.3k
  else if (msg->set_global_address.s)
609
0
    send_address_str=&(msg->set_global_address);
610
23.3k
  else if (default_global_address->s)
611
0
    send_address_str=default_global_address;
612
23.3k
  else
613
23.3k
    send_address_str=&(send_sock->address_str);
614
615
23.3k
  if(send_sock && send_sock->adv_port_str.len)
616
0
    send_port_str=&(send_sock->adv_port_str);
617
23.3k
  else if (msg->set_global_port.s)
618
0
    send_port_str=&(msg->set_global_port);
619
23.3k
  else if (default_global_port->s)
620
0
    send_port_str=default_global_port;
621
23.3k
  else
622
23.3k
    send_port_str=&(send_sock->port_no_str);
623
624
  /* init rcv_address_str & rcv_port_str */
625
23.3k
  if(msg->rcv.bind_address) {
626
0
    if(msg->rcv.bind_address->adv_name_str.len)
627
0
      rcv_address_str=&(msg->rcv.bind_address->adv_name_str);
628
0
    else if (default_global_address->s)
629
0
      rcv_address_str=default_global_address;
630
0
    else
631
0
      rcv_address_str=&(msg->rcv.bind_address->address_str);
632
0
    if(msg->rcv.bind_address->adv_port_str.len)
633
0
      rcv_port_str=&(msg->rcv.bind_address->adv_port_str);
634
0
    else if (default_global_port->s)
635
0
      rcv_port_str=default_global_port;
636
0
    else
637
0
      rcv_port_str=&(msg->rcv.bind_address->port_no_str);
638
0
  }
639
640
46.9k
  for (t = lumps; t && t->u.offset<(unsigned int)max_offset ; t = t->next) {
641
    /* is this lump still valid? (it must not be anchored in a deleted area */
642
23.5k
    if (t->u.offset < s_offset && t->u.offset != last_del) {
643
0
      LM_DBG("skip a %d, buffer offset=%d, lump offset=%d, last_del=%d\n",
644
0
        t->op,s_offset, t->u.offset,last_del);
645
0
      continue;
646
0
    }
647
648
35.3k
    for (r = t->before; r; r = r->before) {
649
11.7k
      switch (r->op) {
650
11.7k
        case LUMP_ADD:
651
11.7k
          new_len += r->len;
652
11.7k
          break;
653
0
        case LUMP_ADD_SUBST:
654
0
          SUBST_LUMP_LEN(r);
655
0
          break;
656
0
        case LUMP_ADD_OPT:
657
          /* skip if this is an OPT lump and the condition is
658
           * not satisfied */
659
0
          if (!lump_check_opt(r, msg, send_sock))
660
0
            goto skip_before;
661
0
          break;
662
0
        case LUMP_SKIP:
663
          /* if a SKIP lump, go to the last in the list*/
664
0
          if (!r->before || !r->before->before)
665
0
            continue;
666
0
          for (; r->before->before; r = r->before)
667
0
            ;
668
0
          break;
669
0
        default:
670
          /* only ADD allowed for before/after */
671
0
            LM_CRIT("invalid op for data lump (%x)\n", r->op);
672
11.7k
      }
673
11.7k
    }
674
23.5k
skip_before:
675
23.5k
    switch (t->op) {
676
117
      case LUMP_DEL:
677
117
        last_del=t->u.offset;
678
679
117
        if (t->u.offset < s_offset) {
680
0
          if (t->u.offset + t->len > s_offset) {
681
0
            new_len -= t->len - (s_offset - t->u.offset);
682
0
            s_offset = t->u.offset + t->len;
683
0
          }
684
117
        } else {
685
117
          new_len -= t->len;
686
117
          s_offset = t->u.offset + t->len;
687
117
        }
688
689
117
        break;
690
23.4k
      case LUMP_NOP:
691
        /* do nothing */
692
23.4k
        break;
693
0
      case LUMP_ADD:
694
        /* FIXME: inconsistent with process_lumps() */
695
0
        new_len += t->len;
696
0
        break;
697
0
      case LUMP_ADD_OPT:
698
0
        LM_BUG("LUMP_ADD_OPT");
699
        /* we don't do anything here, it's only a condition for
700
         * before & after */
701
0
        break;
702
0
      case LUMP_SKIP:
703
0
        LM_BUG("LUMP_SKIP");
704
        /* we don't do anything here, it's only a condition for
705
         * before & after */
706
0
        break;
707
0
      case LUMP_ADD_SUBST:
708
0
        LM_BUG("LUMP_ADD_SUBST");
709
0
        SUBST_LUMP_LEN(t);
710
0
        break;
711
0
      default:
712
0
        LM_BUG("op for data lump (%x)", r->op);
713
23.5k
    }
714
715
41.5k
    for (r = t->after; r; r = r->after) {
716
17.9k
      switch (r->op) {
717
17.9k
        case LUMP_ADD:
718
17.9k
          new_len+=r->len;
719
17.9k
          break;
720
0
        case LUMP_ADD_SUBST:
721
0
          SUBST_LUMP_LEN(r);
722
0
          break;
723
0
        case LUMP_ADD_OPT:
724
          /* skip if this is an OPT lump and the condition is
725
           * not satisfied */
726
0
          if (!lump_check_opt(r, msg, send_sock))
727
0
            goto skip_after;
728
0
          break;
729
0
        case LUMP_SKIP:
730
          /* if a SKIP lump, go to the last in the list*/
731
0
          if (!r->after || !r->after->after)
732
0
            continue;
733
0
          for (; r->after->after; r = r->after)
734
0
            ;
735
0
          break;
736
0
        default:
737
          /* only ADD allowed for before/after */
738
0
          LM_CRIT("invalid op for data lump (%x)\n", r->op);
739
17.9k
      }
740
17.9k
    }
741
23.5k
skip_after:
742
23.5k
    ; /* to make gcc 3.* happy */
743
23.5k
  }
744
23.3k
  return new_len;
745
23.3k
}
746
747
748
749
/*! \brief another helper functions, adds/Removes the lump,
750
  code moved from build_req_from_req  */
751
752
void process_lumps( struct sip_msg* msg,
753
          struct lump* lumps,
754
          char* new_buf,
755
          unsigned int* new_buf_offs,
756
          unsigned int* orig_offs,
757
          const struct socket_info* send_sock,
758
          int max_offset)
759
23.3k
{
760
23.3k
  struct lump *t, *r;
761
23.3k
  char* orig;
762
23.3k
  unsigned int size, offset, s_offset;
763
23.3k
  unsigned int last_del;
764
23.3k
  const str *send_address_str, *send_port_str;
765
23.3k
  const str *rcv_address_str=NULL;
766
23.3k
  const str *rcv_port_str=NULL;
767
768
23.3k
#define SUBST_LUMP(subst_l) \
769
23.3k
  switch((subst_l)->u.subst){ \
770
0
    case SUBST_RCV_IP: \
771
0
      if (msg->rcv.bind_address){  \
772
0
        memcpy(new_buf+offset, rcv_address_str->s, \
773
0
          rcv_address_str->len); \
774
0
        offset+=rcv_address_str->len; \
775
0
      }else{  \
776
        /*FIXME*/ \
777
0
        LM_CRIT("null bind_address\n"); \
778
0
      }; \
779
0
      break; \
780
0
    case SUBST_RCV_PORT: \
781
0
      if (msg->rcv.bind_address){  \
782
0
        memcpy(new_buf+offset, rcv_port_str->s, \
783
0
            rcv_port_str->len); \
784
0
        offset+=rcv_port_str->len; \
785
0
      }else{  \
786
        /*FIXME*/ \
787
0
        LM_CRIT("null bind_address\n"); \
788
0
      }; \
789
0
      break; \
790
0
    case SUBST_RCV_ALL: \
791
0
      if (msg->rcv.bind_address){  \
792
        /* address */ \
793
0
        memcpy(new_buf+offset, rcv_address_str->s, \
794
0
            rcv_address_str->len); \
795
0
        offset+=rcv_address_str->len; \
796
        /* :port */ \
797
0
        if (msg->rcv.bind_address->port_no!=SIP_PORT || (rcv_port_str!=&(msg->rcv.bind_address->port_no_str))){ \
798
0
          new_buf[offset]=':'; offset++; \
799
0
          memcpy(new_buf+offset, \
800
0
              rcv_port_str->s, \
801
0
              rcv_port_str->len); \
802
0
          offset+=rcv_port_str->len; \
803
0
        }\
804
0
        switch(msg->rcv.bind_address->proto){ \
805
          /* TODO: change this to look into protos ! */ \
806
0
          case PROTO_NONE: \
807
0
          case PROTO_UDP: \
808
0
            break; /* nothing to do, udp is default*/ \
809
0
          case PROTO_TCP: \
810
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
811
0
                TRANSPORT_PARAM_LEN); \
812
0
            offset+=TRANSPORT_PARAM_LEN; \
813
0
            memcpy(new_buf+offset, "tcp", 3); \
814
0
            offset+=3; \
815
0
            break; \
816
0
          case PROTO_TLS: \
817
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
818
0
                TRANSPORT_PARAM_LEN); \
819
0
            offset+=TRANSPORT_PARAM_LEN; \
820
0
            memcpy(new_buf+offset, "tls", 3); \
821
0
            offset+=3; \
822
0
            break; \
823
0
          case PROTO_SCTP: \
824
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
825
0
                TRANSPORT_PARAM_LEN); \
826
0
            offset+=TRANSPORT_PARAM_LEN; \
827
0
            memcpy(new_buf+offset, "sctp", 4); \
828
0
            offset+=4; \
829
0
            break; \
830
0
          case PROTO_WS: \
831
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
832
0
                TRANSPORT_PARAM_LEN); \
833
0
            offset+=TRANSPORT_PARAM_LEN; \
834
0
            memcpy(new_buf+offset, "ws", 2); \
835
0
            offset+=2; \
836
0
            break; \
837
0
          case PROTO_WSS: \
838
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
839
0
                TRANSPORT_PARAM_LEN); \
840
0
            offset+=TRANSPORT_PARAM_LEN; \
841
0
            memcpy(new_buf+offset, "wss", 3); \
842
0
            offset+=3; \
843
0
            break; \
844
0
          default: \
845
0
            LM_CRIT("unknown proto %d\n", \
846
0
                msg->rcv.bind_address->proto); \
847
0
        } \
848
0
      }else{  \
849
        /*FIXME*/ \
850
0
        LM_CRIT("null bind_address\n"); \
851
0
      }; \
852
0
      break; \
853
0
    case SUBST_SND_IP: \
854
0
      if (send_sock){  \
855
0
        memcpy(new_buf+offset, send_address_str->s, \
856
0
                  send_address_str->len); \
857
0
        offset+=send_address_str->len; \
858
0
      }else{  \
859
        /*FIXME*/ \
860
0
        LM_CRIT("called with null send_sock\n"); \
861
0
      }; \
862
0
      break; \
863
0
    case SUBST_SND_PORT: \
864
0
      if (send_sock){  \
865
0
        memcpy(new_buf+offset, send_port_str->s, \
866
0
                  send_port_str->len); \
867
0
        offset+=send_port_str->len; \
868
0
      }else{  \
869
        /*FIXME*/ \
870
0
        LM_CRIT("called with null send_sock\n"); \
871
0
      }; \
872
0
      break; \
873
0
    case SUBST_SND_ALL: \
874
0
      if (send_sock){  \
875
        /* address */ \
876
0
        memcpy(new_buf+offset, send_address_str->s, \
877
0
            send_address_str->len); \
878
0
        offset+=send_address_str->len; \
879
        /* :port */ \
880
0
        if ((send_sock->port_no!=SIP_PORT) || \
881
0
          (send_port_str!=&(send_sock->port_no_str))){ \
882
0
          new_buf[offset]=':'; offset++; \
883
0
          memcpy(new_buf+offset, send_port_str->s, \
884
0
              send_port_str->len); \
885
0
          offset+=send_port_str->len; \
886
0
        }\
887
0
        switch(send_sock->proto){ \
888
0
          case PROTO_NONE: \
889
0
          case PROTO_UDP: \
890
0
            break; /* nothing to do, udp is default*/ \
891
0
          case PROTO_TCP: \
892
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
893
0
                TRANSPORT_PARAM_LEN); \
894
0
            offset+=TRANSPORT_PARAM_LEN; \
895
0
            memcpy(new_buf+offset, "tcp", 3); \
896
0
            offset+=3; \
897
0
            break; \
898
0
          case PROTO_TLS: \
899
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
900
0
                TRANSPORT_PARAM_LEN); \
901
0
            offset+=TRANSPORT_PARAM_LEN; \
902
0
            memcpy(new_buf+offset, "tls", 3); \
903
0
            offset+=3; \
904
0
            break; \
905
0
          case PROTO_SCTP: \
906
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
907
0
                TRANSPORT_PARAM_LEN); \
908
0
            offset+=TRANSPORT_PARAM_LEN; \
909
0
            memcpy(new_buf+offset, "sctp", 4); \
910
0
            offset+=4; \
911
0
            break; \
912
0
          case PROTO_WS: \
913
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
914
0
                TRANSPORT_PARAM_LEN); \
915
0
            offset+=TRANSPORT_PARAM_LEN; \
916
0
            memcpy(new_buf+offset, "ws", 2); \
917
0
            offset+=2; \
918
0
            break; \
919
0
          case PROTO_WSS: \
920
0
            memcpy(new_buf+offset, TRANSPORT_PARAM, \
921
0
                TRANSPORT_PARAM_LEN); \
922
0
            offset+=TRANSPORT_PARAM_LEN; \
923
0
            memcpy(new_buf+offset, "wss", 3); \
924
0
            offset+=3; \
925
0
            break; \
926
0
          default: \
927
0
            LM_CRIT("unknown proto %d\n", \
928
0
                send_sock->proto); \
929
0
        } \
930
0
      }else{  \
931
        /*FIXME*/ \
932
0
        LM_CRIT("null bind_address\n"); \
933
0
      }; \
934
0
      break; \
935
0
    case SUBST_RCV_PROTO: \
936
0
      if (msg->rcv.bind_address){ \
937
0
        switch(msg->rcv.bind_address->proto){ \
938
0
          case PROTO_NONE: \
939
0
          case PROTO_UDP: \
940
0
            memcpy(new_buf+offset, "udp", 3); \
941
0
            offset+=3; \
942
0
            break; \
943
0
          case PROTO_TCP: \
944
0
            memcpy(new_buf+offset, "tcp", 3); \
945
0
            offset+=3; \
946
0
            break; \
947
0
          case PROTO_TLS: \
948
0
            memcpy(new_buf+offset, "tls", 3); \
949
0
            offset+=3; \
950
0
            break; \
951
0
          case PROTO_SCTP: \
952
0
            memcpy(new_buf+offset, "sctp", 4); \
953
0
            offset+=4; \
954
0
            break; \
955
0
          case PROTO_WS: \
956
0
            memcpy(new_buf+offset, "ws", 2); \
957
0
            offset+=2; \
958
0
            break; \
959
0
          case PROTO_WSS: \
960
0
            memcpy(new_buf+offset, "wss", 3); \
961
0
            offset+=3; \
962
0
            break; \
963
0
          default: \
964
0
            LM_CRIT("unknown proto %d\n", \
965
0
                msg->rcv.bind_address->proto); \
966
0
        } \
967
0
      }else{  \
968
        /*FIXME*/ \
969
0
        LM_CRIT("called with null send_sock \n"); \
970
0
      }; \
971
0
      break; \
972
0
    case  SUBST_SND_PROTO: \
973
0
      if (send_sock){ \
974
0
        switch(send_sock->proto){ \
975
0
          case PROTO_NONE: \
976
0
          case PROTO_UDP: \
977
0
            memcpy(new_buf+offset, "udp", 3); \
978
0
            offset+=3; \
979
0
            break; \
980
0
          case PROTO_TCP: \
981
0
            memcpy(new_buf+offset, "tcp", 3); \
982
0
            offset+=3; \
983
0
            break; \
984
0
          case PROTO_TLS: \
985
0
            memcpy(new_buf+offset, "tls", 3); \
986
0
            offset+=3; \
987
0
            break; \
988
0
          case PROTO_SCTP: \
989
0
            memcpy(new_buf+offset, "sctp", 4); \
990
0
            offset+=4; \
991
0
            break; \
992
0
          case PROTO_WS: \
993
0
            memcpy(new_buf+offset, "ws", 2); \
994
0
            offset+=2; \
995
0
            break; \
996
0
          case PROTO_WSS: \
997
0
            memcpy(new_buf+offset, "wss", 3); \
998
0
            offset+=3; \
999
0
            break; \
1000
0
          default: \
1001
0
            LM_CRIT("unknown proto %d\n", \
1002
0
                send_sock->proto); \
1003
0
        } \
1004
0
      }else{  \
1005
        /*FIXME*/ \
1006
0
        LM_CRIT("called with null send_sock \n"); \
1007
0
      }; \
1008
0
      break; \
1009
0
    default: \
1010
0
          LM_CRIT("unknown subst type %d\n", \
1011
0
              (subst_l)->u.subst); \
1012
0
  } \
1013
23.3k
 \
1014
23.3k
1015
  /* init send_address_str & send_port_str */
1016
23.3k
  if(send_sock && send_sock->adv_name_str.len)
1017
0
    send_address_str=&(send_sock->adv_name_str);
1018
23.3k
  else if (msg->set_global_address.len)
1019
0
    send_address_str=&(msg->set_global_address);
1020
23.3k
  else if (default_global_address->s)
1021
0
    send_address_str=default_global_address;
1022
23.3k
  else
1023
23.3k
    send_address_str=&(send_sock->address_str);
1024
23.3k
  if(send_sock && send_sock->adv_port_str.len)
1025
0
    send_port_str=&(send_sock->adv_port_str);
1026
23.3k
  else if (msg->set_global_port.len)
1027
0
    send_port_str=&(msg->set_global_port);
1028
23.3k
  else if (default_global_port->s)
1029
0
    send_port_str=default_global_port;
1030
23.3k
  else
1031
23.3k
    send_port_str=&(send_sock->port_no_str);
1032
1033
  /* init rcv_address_str & rcv_port_str */
1034
23.3k
  if(msg->rcv.bind_address) {
1035
0
    if(msg->rcv.bind_address->adv_name_str.len)
1036
0
      rcv_address_str=&(msg->rcv.bind_address->adv_name_str);
1037
0
    else if (default_global_address->s)
1038
0
      rcv_address_str=default_global_address;
1039
0
    else
1040
0
      rcv_address_str=&(msg->rcv.bind_address->address_str);
1041
0
    if(msg->rcv.bind_address->adv_port_str.len)
1042
0
      rcv_port_str=&(msg->rcv.bind_address->adv_port_str);
1043
0
    else if (default_global_port->s)
1044
0
      rcv_port_str=default_global_port;
1045
0
    else
1046
0
      rcv_port_str=&(msg->rcv.bind_address->port_no_str);
1047
0
  }
1048
1049
23.3k
  orig=msg->buf;
1050
23.3k
  offset=*new_buf_offs;
1051
23.3k
  s_offset=*orig_offs;
1052
23.3k
  last_del=0;
1053
1054
46.9k
  for (t = lumps; t && t->u.offset<(unsigned int)max_offset ; t = t->next) {
1055
    /* skip this lump if the "offset" is still in a "deleted" area */
1056
23.5k
    if (t->u.offset < s_offset && t->u.offset != last_del) {
1057
0
      LM_DBG("skip a %d, buffer offset=%d, lump offset=%d, last_del=%d\n",
1058
0
        t->op,s_offset, t->u.offset,last_del);
1059
0
      continue;
1060
0
    }
1061
1062
23.5k
    switch (t->op) {
1063
23.4k
      case LUMP_NOP:
1064
23.5k
      case LUMP_DEL:
1065
        /* copy till offset (if any) */
1066
23.5k
        if (s_offset < t->u.offset) {
1067
23.5k
          size = t->u.offset-s_offset;
1068
23.5k
          memcpy(new_buf+offset, orig+s_offset, size);
1069
23.5k
          offset += size;
1070
23.5k
          s_offset += size;
1071
23.5k
        }
1072
1073
23.5k
        if (t->op == LUMP_DEL)
1074
117
          last_del = t->u.offset;
1075
1076
        /* process before  */
1077
35.3k
        for (r = t->before; r; r = r->before) {
1078
11.7k
          switch (r->op) {
1079
11.7k
            case LUMP_ADD:
1080
              /*just add it here*/
1081
11.7k
              memcpy(new_buf+offset, r->u.value, r->len);
1082
11.7k
              offset += r->len;
1083
11.7k
              break;
1084
0
            case LUMP_ADD_SUBST:
1085
0
              SUBST_LUMP(r);
1086
0
              break;
1087
0
            case LUMP_ADD_OPT:
1088
              /* skip if this is an OPT lump and the condition is
1089
              * not satisfied */
1090
0
              if (!lump_check_opt(r, msg, send_sock))
1091
0
                goto skip_nop_before;
1092
0
              break;
1093
0
            case LUMP_SKIP:
1094
              /* if a SKIP lump, go to the last in the list*/
1095
0
              if (!r->before || !r->before->before)
1096
0
                continue;
1097
0
              for (; r->before->before; r = r->before)
1098
0
                ;
1099
0
              break;
1100
0
            default:
1101
              /* only ADD allowed for before/after */
1102
0
              LM_BUG("invalid op 1 (%x)",r->op);
1103
11.7k
          }
1104
11.7k
        }
1105
23.5k
skip_nop_before:
1106
23.5k
        if (t->op == LUMP_DEL) {
1107
          /*
1108
           * skip at most len bytes from orig msg
1109
           * and properly handle DEL lumps at the same offset --liviu
1110
           */
1111
117
          if (t->u.offset + t->len > s_offset)
1112
117
            s_offset += t->len - (s_offset - t->u.offset);
1113
117
        }
1114
1115
        /* process after */
1116
41.5k
        for (r = t->after; r; r = r->after) {
1117
17.9k
          switch (r->op) {
1118
17.9k
            case LUMP_ADD:
1119
              /*just add it here*/
1120
17.9k
              memcpy(new_buf+offset, r->u.value, r->len);
1121
17.9k
              offset += r->len;
1122
17.9k
              break;
1123
0
            case LUMP_ADD_SUBST:
1124
0
              SUBST_LUMP(r);
1125
0
              break;
1126
0
            case LUMP_ADD_OPT:
1127
              /* skip if this is an OPT lump and the condition is
1128
              * not satisfied */
1129
0
              if (!lump_check_opt(r, msg, send_sock))
1130
0
                goto skip_nop_after;
1131
0
              break;
1132
0
            case LUMP_SKIP:
1133
              /* if a SKIP lump, go to the last in the list*/
1134
0
              if (!r->after || !r->after->after)
1135
0
                continue;
1136
0
              for (; r->after->after; r = r->after)
1137
0
                ;
1138
0
              break;
1139
0
            default:
1140
              /* only ADD allowed for before/after */
1141
0
              LM_BUG("invalid op 2 (%x)", r->op);
1142
17.9k
          }
1143
17.9k
        }
1144
23.5k
skip_nop_after:
1145
23.5k
        break;
1146
23.5k
      case LUMP_ADD:
1147
0
      case LUMP_ADD_SUBST:
1148
0
      case LUMP_ADD_OPT:
1149
0
        LM_BUG("ADD|SUBST|OPT");
1150
        /* skip if this is an OPT lump and the condition is
1151
         * not satisfied */
1152
0
        if ((t->op==LUMP_ADD_OPT) &&
1153
0
            (!lump_check_opt(t, msg, send_sock)))
1154
0
          continue;
1155
        /* just add it here! */
1156
        /* process before  */
1157
0
        for(r=t->before;r;r=r->before){
1158
0
          switch (r->op){
1159
0
            case LUMP_ADD:
1160
              /*just add it here*/
1161
0
              memcpy(new_buf+offset, r->u.value, r->len);
1162
0
              offset+=r->len;
1163
0
              break;
1164
0
            case LUMP_ADD_SUBST:
1165
0
              SUBST_LUMP(r);
1166
0
              break;
1167
0
            case LUMP_ADD_OPT:
1168
              /* skip if this is an OPT lump and the condition is
1169
              * not satisfied */
1170
0
              if (!lump_check_opt(r, msg, send_sock))
1171
0
                goto skip_before;
1172
0
              break;
1173
0
            case LUMP_SKIP:
1174
              /* if a SKIP lump, go to the last in the list*/
1175
0
              if (!r->before || !r->before->before) continue;
1176
0
              for(;r->before->before;r=r->before);
1177
0
              break;
1178
0
            default:
1179
              /* only ADD allowed for before/after */
1180
0
              LM_BUG("invalid op 3 (%x)", r->op);
1181
0
          }
1182
0
        }
1183
0
skip_before:
1184
        /* copy "main" part */
1185
0
        switch(t->op){
1186
0
          case LUMP_ADD:
1187
0
            memcpy(new_buf+offset, t->u.value, t->len);
1188
0
            offset+=t->len;
1189
0
            break;
1190
0
          case LUMP_ADD_SUBST:
1191
0
            SUBST_LUMP(t);
1192
0
            break;
1193
0
          case LUMP_ADD_OPT:
1194
            /* do nothing, it's only a condition */
1195
0
            break;
1196
0
          default:
1197
            /* should not ever get here */
1198
0
            LM_BUG("invalid op 4 %d", t->op);
1199
0
        }
1200
        /* process after */
1201
0
        for(r=t->after;r;r=r->after){
1202
0
          switch (r->op){
1203
0
            case LUMP_ADD:
1204
              /*just add it here*/
1205
0
              memcpy(new_buf+offset, r->u.value, r->len);
1206
0
              offset+=r->len;
1207
0
              break;
1208
0
            case LUMP_ADD_SUBST:
1209
0
              SUBST_LUMP(r);
1210
0
              break;
1211
0
            case LUMP_ADD_OPT:
1212
              /* skip if this is an OPT lump and the condition is
1213
              * not satisfied */
1214
0
              if (!lump_check_opt(r, msg, send_sock))
1215
0
                goto skip_after;
1216
0
              break;
1217
0
            case LUMP_SKIP:
1218
              /* if a SKIP lump, go to the last in the list*/
1219
0
              if (!r->after || !r->after->after) continue;
1220
0
              for(;r->after->after;r=r->after);
1221
0
              break;
1222
0
            default:
1223
              /* only ADD allowed for before/after */
1224
0
              LM_BUG("invalid op 5 (%x)", r->op);
1225
0
          }
1226
0
        }
1227
0
skip_after:
1228
0
        break;
1229
0
      case LUMP_SKIP:
1230
0
        LM_BUG("LUMP_SKIP");
1231
        /* if a SKIP lump, go to the last in the list*/
1232
0
        if (!t->next || !t->next->next)
1233
0
          continue;
1234
0
        for (; t->next->next; t = t->next)
1235
0
          ;
1236
0
        break;
1237
0
      default:
1238
0
        LM_BUG("invalid op 6 (%x)", t->op);
1239
23.5k
    }
1240
23.5k
  }
1241
1242
23.3k
  *new_buf_offs = offset;
1243
23.3k
  *orig_offs = s_offset;
1244
23.3k
}
1245
1246
1247
/* Prepares a body to be re-assembled. This consists of the following ops:
1248
 *   - run the functions to build the parts (if the case)
1249
 *   - add SIP header lumps to change CT header 
1250
 *   - estimating the new len of the body (after applying all the changes)
1251
 * IMPORTANT: keep this function in sync with the reassemble_body_parts()
1252
 *    to be 100% that estimating and building the body leads to the same
1253
 *    result (as len).
1254
 */
1255
unsigned int prep_reassemble_body_parts( struct sip_msg* msg,
1256
                        const struct socket_info* send_sock)
1257
125
{
1258
125
  struct body_part *part;
1259
125
  struct lump* lump;
1260
125
  struct lump* ct;
1261
125
  unsigned int size;
1262
125
  unsigned int len = 0;
1263
125
  unsigned int orig_offs;
1264
125
  struct hdr_field hf;
1265
125
  char *hdr, *it;
1266
1267
  /* set the offset (in the original buffer) at the beginning of the body */
1268
125
  orig_offs = (msg->body && msg->body->body.s) ?
1269
125
    msg->body->body.s-msg->buf : msg->len ;
1270
1271
125
  if (msg->body->updated_part_count==0) {
1272
1273
    /* no body to be placed in the new msg !
1274
     * simply skip the entire body */
1275
0
    LM_DBG("no part to be added\n");
1276
1277
    /* Remove Content-Type hdr if present */
1278
0
    if (msg->content_type && msg->content_type->name.s
1279
0
    && msg->content_type->name.len
1280
0
    && del_lump(msg, msg->content_type->name.s- msg->buf,
1281
0
    msg->content_type->len, HDR_CONTENTTYPE_T)==0) {
1282
0
      LM_ERR("failed to add lump to delete content type header\n");
1283
0
    }
1284
1285
125
  } else if (msg->body->updated_part_count==1) {
1286
1287
    /* there is only one part to be added, so iterate
1288
     * and find it */
1289
125
    LM_DBG("only one part to be added\n");
1290
1291
125
    for( part=&msg->body->first ; part ; part=part->next)
1292
125
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED)==0 ) break;
1293
1294
125
    if (part==NULL) {
1295
0
      LM_BUG("updated count is 1, but no non-deleted part found :-/\n");
1296
0
      return len /* 0 */;
1297
0
    }
1298
1299
125
    LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1300
125
      part->flags, part->mime_s.len, part->mime_s.s, part->dump_f);
1301
1302
125
    if (part->dump_f) {
1303
      /* trigger the the dump function link the resulting buffer
1304
       * as 'dump' (and to be used and freed when the body buffer
1305
       * is actually built) */
1306
0
      if (part->dump_f( part->parsed ,msg, &part->dump)<0) {
1307
0
        LM_ERR("failed to build part, inserting empty\n");
1308
0
        part->dump.s = "";
1309
0
        part->dump.len = 0;
1310
0
      } else
1311
0
        len += part->dump.len;
1312
125
    } else {
1313
125
      if ( part->flags & SIP_BODY_PART_FLAG_NEW ) {
1314
        /* simpy copy the body of the part */
1315
0
        len += part->body.len;
1316
125
      } else {
1317
        /* this is one part that was received (so potentially
1318
         * modified during runtime) -> apply all body lumps
1319
         * inside this part */
1320
125
        orig_offs = part->body.s - msg->buf;
1321
125
        lump = msg->body_lumps;
1322
125
        while ( lump && lump->u.offset < orig_offs )
1323
0
          lump=lump->next;
1324
125
        if (lump) {
1325
0
          LM_DBG("lumps found in the part, applying...\n");
1326
0
          len += lumps_len( msg, lump, send_sock, 
1327
0
            part->body.s+part->body.len-msg->buf);
1328
0
        }
1329
        /* and copy whatever is left, all the way to the end of part */
1330
125
        len += (part->body.s+part->body.len-msg->buf)-orig_offs;
1331
125
      }
1332
125
    }
1333
1334
    /* if the part is new (0->1 addition or 1->1 replacement) or
1335
     * if the part is kept from a stipped multi-part  (n->1)
1336
     *   =>  replace the msg content-type with the new one */
1337
125
    if ( (part->flags & SIP_BODY_PART_FLAG_NEW)
1338
125
    || msg->body->part_count>1 ) {
1339
      /* replace the Content-Type hdr */
1340
0
      if (msg->content_type)
1341
0
        ct = del_lump(msg, msg->content_type->name.s-msg->buf,
1342
0
          msg->content_type->len, HDR_CONTENTTYPE_T);
1343
0
      else
1344
0
        ct = anchor_lump(msg, msg->unparsed - msg->buf,
1345
0
          HDR_CONTENTTYPE_T);
1346
0
      if (ct==NULL) {
1347
0
        LM_ERR("failed to remove old CT / create anchor\n");
1348
0
      } else {
1349
        /* if a new part, we need to build the CT header; if a 
1350
         * received part, simply copied from the part */
1351
0
        if (part->flags & SIP_BODY_PART_FLAG_NEW) {
1352
0
          hdr = (char*)pkg_malloc( 14 + part->mime_s.len +CRLF_LEN +
1353
0
            part->headers.len);
1354
0
          if (hdr==NULL) {
1355
0
            LM_ERR("failed to allocate new ct hdr\n");
1356
0
          } else {
1357
0
            memcpy( hdr, "Content-Type: ", 14);
1358
0
            memcpy( hdr+14, part->mime_s.s, part->mime_s.len);
1359
0
            memcpy( hdr+14+part->mime_s.len, CRLF, CRLF_LEN);
1360
0
            if (part->headers.len)
1361
0
              memcpy( hdr+14+part->mime_s.len+CRLF_LEN,
1362
0
                part->headers.s, part->headers.len);
1363
0
            if (insert_new_lump_before(ct, hdr,
1364
0
            14+part->mime_s.len+CRLF_LEN+part->headers.len,
1365
0
            HDR_CONTENTTYPE_T) == NULL) {
1366
0
              LM_ERR("failed to create insert lump\n");
1367
0
              pkg_free(hdr);
1368
0
            }
1369
0
          }
1370
0
        } else {
1371
          /* iterate all the SIP hdrs from this part and keep all
1372
           * except the "Content-Length" */
1373
0
          it = part->headers.s;
1374
0
          while ( it<part->headers.s+part->headers.len ) {
1375
0
            memset( &hf, 0, sizeof(struct hdr_field));
1376
0
            it = get_hdr_field( it, part->headers.s+part->headers.len, &hf);
1377
0
            if (hf.type==HDR_ERROR_T || hf.type==HDR_EOH_T)
1378
0
              break;
1379
0
            if (hf.type==HDR_CONTENTLENGTH_T)
1380
0
              continue;
1381
            /* add this hdr */
1382
0
            hdr = (char*)pkg_malloc( hf.len);
1383
0
            if (hdr==NULL) {
1384
0
              LM_ERR("failed to allocate new ct hdr\n");
1385
0
            } else {
1386
0
              memcpy( hdr, hf.name.s, hf.len);
1387
0
              if (insert_new_lump_before(ct, hdr,
1388
0
              hf.len, HDR_CONTENTTYPE_T) == NULL) {
1389
0
                LM_ERR("failed to create insert lump\n");
1390
0
                pkg_free(hdr);
1391
0
              }
1392
0
            }
1393
0
          }
1394
0
        }
1395
0
      }
1396
0
    } else
1397
      /* if it is an 1->1 keeping the part, try to preserve the
1398
       * the packing (multi-part or not) of this part */
1399
125
      if ( (part->flags & SIP_BODY_PART_FLAG_NEW)==0 &&
1400
125
      msg->body->part_count==1 &&
1401
125
      msg->body->flags & SIP_BODY_RCV_MULTIPART) {
1402
        /* preserve the original multi-part packing by preserving
1403
         * the before and after padding between part and body */
1404
0
        len += msg->body->body.len - part->body.len;
1405
0
      }
1406
1407
125
  } else if (msg->body->part_count<2) {
1408
1409
    /* transition from 0/1 to multiple parts,
1410
     * so we need to add boundries */
1411
1412
0
    LM_DBG("transition from 0/1 parts to multi part body\n");
1413
0
    lump = msg->body_lumps;
1414
1415
0
    for( part=&msg->body->first ; part ; part=part->next) {
1416
1417
0
      LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1418
0
        part->flags, part->mime_s.len, part->mime_s.s, part->dump_f);
1419
1420
      /* skip deleted parts */
1421
0
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED) ) {
1422
0
        if ((part->flags & SIP_BODY_PART_FLAG_NEW) == 0)
1423
          /* reposition at the end of the skipped body */
1424
0
          orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN;
1425
0
        continue;
1426
0
      }
1427
1428
      /* separator and CT header */
1429
0
      len += 2 /* "--" */ + sizeof(OSS_BOUNDARY)-1 + CRLF_LEN +
1430
0
       14/* "Content-Type: " */ + part->mime_s.len +
1431
0
       CRLF_LEN + part->headers.len + CRLF_LEN ;
1432
1433
      /* part with dump function ? */
1434
0
      if (part->dump_f) {
1435
0
        if (part->dump_f( part->parsed ,msg, &part->dump)<0) {
1436
0
          LM_ERR("failed to build part, inserting empty\n");
1437
0
          part->dump.s = "";
1438
0
          part->dump.len = 0;
1439
0
        } else
1440
0
          len += part->dump.len;
1441
0
        len += CRLF_LEN;
1442
0
      } else
1443
      /* new part with body attached */
1444
0
      if ( part->flags & SIP_BODY_PART_FLAG_NEW ) {
1445
        /* simpy copy the body of the part */
1446
0
        len += part->body.len;
1447
0
        len += CRLF_LEN;
1448
0
      } else
1449
      /* old part with lumps */
1450
0
      {
1451
        /* first find the first lump inside our body part */
1452
0
        while ( lump && lump->u.offset<(part->body.s-msg->buf) )
1453
0
          lump=lump->next;
1454
0
        if (lump) {
1455
0
          LM_DBG("lumps found in the part, applying...\n");
1456
          /* apply the lumps */
1457
0
          len += lumps_len( msg, lump, send_sock,
1458
0
            part->body.s+part->body.len-msg->buf);
1459
0
        }
1460
        /* and copy whatever is left, all the way to the end of part */
1461
0
        size = (part->body.s+part->body.len-msg->buf)-orig_offs;
1462
0
        len += size + CRLF_LEN;
1463
0
      }
1464
1465
      /* reposition at the end of the processed body */
1466
0
      if ((part->flags & SIP_BODY_PART_FLAG_NEW) == 0)
1467
0
        orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN;
1468
1469
0
    } /* end for(over the parts) */
1470
1471
    /* the final separator */
1472
0
    len += 2 /* "--" */ + sizeof(OSS_BOUNDARY)-1 + 2 /* "--" */ + CRLF_LEN;
1473
1474
    /* replace the Content-Type hdr */
1475
0
    if (msg->content_type)
1476
0
      ct = del_lump(msg, msg->content_type->name.s-msg->buf,
1477
0
        msg->content_type->len, HDR_CONTENTTYPE_T);
1478
0
    else
1479
0
      ct = anchor_lump(msg, msg->unparsed - msg->buf,
1480
0
        HDR_CONTENTTYPE_T);
1481
0
    if (ct==NULL) {
1482
0
      LM_ERR("failed to remove old CT / create anchor\n");
1483
0
    } else {
1484
      /* "Content-Type: multipart/mixed;boundary=OSS_BOUNDARY CRLF" */
1485
0
      hdr = (char*)pkg_malloc( 39 + sizeof(OSS_BOUNDARY)-1 + CRLF_LEN );
1486
0
      if (hdr==NULL) {
1487
0
        LM_ERR("failed to allocate new ct hdr\n");
1488
0
      } else {
1489
0
        memcpy( hdr,
1490
0
        "Content-Type: multipart/mixed;boundary=" OSS_BOUNDARY CRLF,
1491
0
        39 + sizeof(OSS_BOUNDARY)-1 + CRLF_LEN);
1492
0
        if (insert_new_lump_before(ct, hdr,
1493
0
        39 + sizeof(OSS_BOUNDARY)-1 + CRLF_LEN,
1494
0
        HDR_CONTENTTYPE_T) == NULL) {
1495
0
          LM_ERR("failed to create insert lump\n");
1496
0
          pkg_free(hdr);
1497
0
        }
1498
0
      }
1499
0
    }
1500
1501
0
  } else {
1502
1503
    /* multi to multi parts - iterate the list, handle insert new parts,
1504
     * remove old ones, and modify the kept ones (if the case) */
1505
1506
0
    LM_DBG("multi to multi part body reconstruction\n");
1507
0
    lump = msg->body_lumps;
1508
1509
0
    for( part=&msg->body->first ; part ; part=part->next) {
1510
      /* skip deleted parts */
1511
0
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED) ) {
1512
0
        if ( (part->flags & SIP_BODY_PART_FLAG_NEW) == 0 )
1513
          /* reposition at the end of the skipped body */
1514
0
          orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN;
1515
0
        continue;
1516
0
      }
1517
1518
0
      LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1519
0
        part->flags, part->mime_s.len, part->mime_s.s, part->dump_f);
1520
1521
      /* new part ? */
1522
0
      if ( part->flags & SIP_BODY_PART_FLAG_NEW ) {
1523
        /* separator and CT header */
1524
0
        len += 2 /* "--" */ + msg->body->boundary.len +
1525
0
          CRLF_LEN + 14 /* "Content-Type: " */ + part->mime_s.len +
1526
0
          CRLF_LEN + part->headers.len + CRLF_LEN ;
1527
        /* simpy copy the body of the part */
1528
0
        if (part->dump_f) {
1529
0
          if (part->dump_f( part->parsed ,msg, &part->dump)<0) {
1530
0
            LM_ERR("failed to build part, inserting empty\n");
1531
0
            part->dump.s = "";
1532
0
            part->dump.len = 0;
1533
0
          } else
1534
0
            len += part->dump.len;
1535
0
        } else
1536
0
          len += part->body.len;
1537
0
        len += CRLF_LEN;
1538
0
      } else
1539
      /* old part with dump function */
1540
0
      if (part->dump_f) {
1541
        /* copy separator and headers from original message */
1542
0
        len += (part->body.s - msg->buf) - orig_offs;
1543
        /* put in the new body */
1544
0
        if (part->dump_f( part->parsed ,msg, &part->dump)<0) {
1545
0
          LM_ERR("failed to build part, inserting empty\n");
1546
0
          part->dump.s = "";
1547
0
          part->dump.len = 0;
1548
0
        } else
1549
0
          len += part->dump.len;
1550
0
        len += CRLF_LEN;
1551
        /* skip the old body */
1552
0
      } else
1553
      /* old part with lumps -> apply changes */
1554
0
      {
1555
        /* first find the first lump inside our body part
1556
         * NOTE: we do not need to explicitly copy the separtor and
1557
         * the headers as they will be automatically got by the 
1558
         * first lup or by the final copy */
1559
0
        while ( lump && lump->u.offset<(part->body.s-msg->buf) )
1560
0
          lump=lump->next;
1561
0
        if (lump) {
1562
0
          LM_DBG("lumps found in the part, applying...\n");
1563
          /* apply the lumps */
1564
0
          len += lumps_len( msg, lump, send_sock,
1565
0
              part->body.s+part->body.len-msg->buf);
1566
0
        }
1567
        /* and copy whatever is left, all the way to the end of part */
1568
0
        size = (part->body.s+part->body.len-msg->buf+CRLF_LEN)-orig_offs;
1569
0
        len += size;
1570
0
      }
1571
1572
      /* reposition at the end of the processed body */
1573
0
      if ((part->flags & SIP_BODY_PART_FLAG_NEW) == 0)
1574
0
        orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN;
1575
0
    } /* end for(over the parts) */
1576
1577
    /* the final separator */
1578
0
    size = msg->len - orig_offs;
1579
0
    len += size;
1580
1581
    /* Content-Type hdr does not require changes in this case */
1582
0
  }
1583
1584
125
  LM_DBG("resulting body len is %d\n",len);
1585
125
  return len;
1586
125
}
1587
1588
1589
void reassemble_body_parts( struct sip_msg* msg, char* new_buf,
1590
            unsigned int* new_offs, unsigned int* orig_offs,
1591
            const struct socket_info* send_sock)
1592
125
{
1593
125
  struct body_part *part;
1594
125
  struct lump* lump;
1595
125
  unsigned int size;
1596
125
  unsigned int offset;
1597
125
  int padding=0;
1598
1599
125
  if (msg->body->updated_part_count==0) {
1600
1601
    /* no body to be placed in the new msg !
1602
     * simply skip the entire body */
1603
0
    LM_DBG("no part to be added\n");
1604
1605
125
  } else if (msg->body->updated_part_count==1) {
1606
1607
    /* there is only one part to be added, so iterate
1608
     * and find it */
1609
125
    LM_DBG("only one part to be added\n");
1610
1611
125
    for( part=&msg->body->first ; part ; part=part->next)
1612
125
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED)==0 ) break;
1613
1614
125
    if (part==NULL) {
1615
0
      LM_BUG("updated count is 1, but no non-deleted part found :-/\n");
1616
0
      return;
1617
0
    }
1618
1619
125
    LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1620
125
      part->flags, part->mime_s.len, part->mime_s.s, part->dump_f);
1621
1622
    /* handle the special case of preserving a single part which was
1623
     * received packed as multipart -> copy the boundries as
1624
     * received */
1625
125
    if ( msg->body->flags & SIP_BODY_RCV_MULTIPART &&
1626
0
    msg->body->part_count==1 &&
1627
0
    (part->flags & SIP_BODY_PART_FLAG_NEW)==0 ) {
1628
      /* copy whatever is between the beginning of the msg body 
1629
       * and the part body*/
1630
0
      memcpy(new_buf+*new_offs, msg->body->body.s,
1631
0
        part->body.s-msg->body->body.s );
1632
0
      *new_offs += part->body.s-msg->body->body.s;
1633
0
      padding = 1;
1634
0
    }
1635
1636
125
    if (part->dump_f) {
1637
      /* the dump function was triggered when the length was computed
1638
       * and the resulting buffer was linked as 'dump' (and we need
1639
       * to free it now) */
1640
      /* copy the new body of the part */
1641
0
      memcpy(new_buf+*new_offs, part->dump.s, part->dump.len );
1642
0
      *new_offs += part->dump.len;
1643
0
      pkg_free(part->dump.s);
1644
0
      part->dump.s = NULL;
1645
0
      part->dump.len = 0;
1646
125
    } else {
1647
125
      if ( part->flags & SIP_BODY_PART_FLAG_NEW ) {
1648
        /* simply copy the body of the part */
1649
0
        memcpy(new_buf+*new_offs, part->body.s, part->body.len );
1650
0
        *new_offs += part->body.len;
1651
125
      } else {
1652
        /* this is one part that was received (so potentially
1653
         * modified during runtime) -> apply all body lumps
1654
         * inside this part */
1655
125
        *orig_offs = part->body.s - msg->buf;
1656
125
        lump = msg->body_lumps;
1657
125
        while ( lump && lump->u.offset<(part->body.s-msg->buf) )
1658
0
          lump=lump->next;
1659
125
        if (lump) {
1660
0
          LM_DBG("lumps found in the part, applying...\n");
1661
          /* apply the lumps */
1662
0
          process_lumps( msg, lump, new_buf, new_offs, orig_offs,
1663
0
            send_sock, part->body.s+part->body.len-msg->buf);
1664
0
        }
1665
        /* and copy whatever is left, all the way to the end of part */
1666
125
        size = (part->body.s+part->body.len-msg->buf)-*orig_offs;
1667
125
        memcpy(new_buf+*new_offs, msg->buf+*orig_offs, size);
1668
125
        *new_offs += size;
1669
125
      }
1670
125
    }
1671
1672
125
    if (padding) {
1673
      /* copy whatever is between the end of the part body 
1674
       * and the end of the msg body*/
1675
0
      memcpy(new_buf+*new_offs, part->body.s+part->body.len,
1676
0
        (msg->body->body.s+msg->body->body.len)-
1677
0
        (part->body.s+part->body.len) );
1678
0
      *new_offs += (msg->body->body.s+msg->body->body.len)-
1679
0
        (part->body.s+part->body.len);
1680
0
    }
1681
1682
125
  } else if (msg->body->part_count<2) {
1683
1684
    /* transition from 0/1 to multiple parts,
1685
     * so we need to add boundries */
1686
1687
0
    LM_DBG("transition from 0/1 parts to multi part body\n");
1688
0
    offset = *new_offs;
1689
0
    lump = msg->body_lumps;
1690
1691
0
    for( part=&msg->body->first ; part ; part=part->next) {
1692
1693
0
      LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1694
0
        part->flags, part->mime_s.len, part->mime_s.s, part->dump_f);
1695
1696
      /* skip deleted parts */
1697
0
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED) ) {
1698
0
        if ((part->flags & SIP_BODY_PART_FLAG_NEW) == 0)
1699
          /* reposition at the end of the skipped body */
1700
0
          *orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN;
1701
0
        continue;
1702
0
      }
1703
1704
      /* separator and CT header */
1705
0
      memcpy(new_buf+offset, "--" OSS_BOUNDARY CRLF "Content-Type: ",
1706
0
        2 + sizeof(OSS_BOUNDARY)-1 + CRLF_LEN + 14);
1707
0
      offset += 2 + sizeof(OSS_BOUNDARY)-1 + CRLF_LEN + 14;
1708
0
      memcpy(new_buf+offset, part->mime_s.s , part->mime_s.len);
1709
0
      offset += part->mime_s.len;
1710
0
      if (part->headers.len==0) {
1711
0
        memcpy(new_buf+offset, CRLF CRLF , CRLF_LEN+CRLF_LEN);
1712
0
        offset += CRLF_LEN + CRLF_LEN ;
1713
0
      } else {
1714
0
        memcpy(new_buf+offset, CRLF , CRLF_LEN);
1715
0
        offset += CRLF_LEN;
1716
0
        memcpy(new_buf+offset, part->headers.s , part->headers.len);
1717
0
        offset += part->headers.len ;
1718
0
        memcpy(new_buf+offset, CRLF , CRLF_LEN);
1719
0
        offset += CRLF_LEN;
1720
0
      }
1721
1722
      /* part with dump function ? */
1723
0
      if (part->dump_f) {
1724
0
        memcpy(new_buf+offset, part->dump.s, part->dump.len );
1725
0
        offset += part->dump.len;
1726
0
        pkg_free(part->dump.s);
1727
0
        part->dump.s = NULL;
1728
0
        part->dump.len = 0;
1729
0
        memcpy(new_buf+offset, CRLF , CRLF_LEN);
1730
0
        offset += CRLF_LEN;
1731
0
      } else
1732
      /* new part with body attached */
1733
0
      if ( part->flags & SIP_BODY_PART_FLAG_NEW ) {
1734
        /* simpy copy the body of the part */
1735
0
        memcpy(new_buf+offset, part->body.s, part->body.len );
1736
0
        offset += part->body.len;
1737
0
        memcpy(new_buf+offset, CRLF , CRLF_LEN);
1738
0
        offset += CRLF_LEN;
1739
0
      } else
1740
      /* old part with lumps */
1741
0
      {
1742
        /* first find the first lump inside our body part */
1743
0
        while ( lump && lump->u.offset<(part->body.s-msg->buf) )
1744
0
          lump=lump->next;
1745
0
        if (lump) {
1746
0
          LM_DBG("lumps found in the part, applying...\n");
1747
          /* apply the lumps */
1748
0
          process_lumps( msg, lump, new_buf, &offset, orig_offs,
1749
0
            send_sock, part->body.s+part->body.len-msg->buf);
1750
0
        }
1751
        /* and copy whatever is left, all the way to the end of part */
1752
0
        size = (part->body.s+part->body.len-msg->buf)-*orig_offs;
1753
0
        memcpy(new_buf+offset, msg->buf+*orig_offs, size);
1754
0
        offset += size;
1755
0
        memcpy(new_buf+offset, CRLF , CRLF_LEN);
1756
0
        offset += CRLF_LEN;
1757
0
      }
1758
1759
      /* reposition at the end of the processed body */
1760
0
      if ((part->flags & SIP_BODY_PART_FLAG_NEW) == 0)
1761
0
        *orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN ;
1762
1763
0
    } /* end for(over the parts) */
1764
1765
    /* the final separator */
1766
0
    memcpy(new_buf+offset, "--" OSS_BOUNDARY "--" CRLF,
1767
0
      2 + sizeof(OSS_BOUNDARY)-1 + 2 + CRLF_LEN);
1768
0
    offset += 2 + sizeof(OSS_BOUNDARY)-1 + 2 + CRLF_LEN;
1769
1770
    /*done here !!*/
1771
0
    *new_offs = offset;
1772
1773
0
  } else {
1774
1775
    /* multi to multi parts - iterate the list, handle insert new parts,
1776
     * remove old ones, and modify the kept ones (if the case) */
1777
0
    LM_DBG("multi to multi part body reconstruction\n");
1778
1779
0
    offset = *new_offs;
1780
0
    lump = msg->body_lumps;
1781
0
    for( part=&msg->body->first ; part ; part=part->next) {
1782
      /* skip deleted parts */
1783
0
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED) ) {
1784
0
        if ( (part->flags & SIP_BODY_PART_FLAG_NEW) == 0 )
1785
          /* reposition at the end of the skipped body */
1786
0
          *orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN;
1787
0
        continue;
1788
0
      }
1789
1790
0
      LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1791
0
        part->flags, part->mime_s.len, part->mime_s.s, part->dump_f);
1792
1793
      /* new part ? */
1794
0
      if ( part->flags & SIP_BODY_PART_FLAG_NEW ) {
1795
        /* separator and CT header */
1796
0
        memcpy(new_buf+offset, "--" , 2);
1797
0
        offset += 2;
1798
0
        memcpy(new_buf+offset, msg->body->boundary.s , msg->body->boundary.len);
1799
0
        offset += msg->body->boundary.len;
1800
0
        memcpy(new_buf+offset, CRLF "Content-Type: " , CRLF_LEN+14);
1801
0
        offset += CRLF_LEN + 14 ;
1802
0
        memcpy(new_buf+offset, part->mime_s.s , part->mime_s.len);
1803
0
        offset += part->mime_s.len;
1804
0
        if (part->headers.len==0) {
1805
0
          memcpy(new_buf+offset, CRLF CRLF , CRLF_LEN+CRLF_LEN);
1806
0
          offset += CRLF_LEN + CRLF_LEN ;
1807
0
        } else {
1808
0
          memcpy(new_buf+offset, CRLF , CRLF_LEN);
1809
0
          offset += CRLF_LEN;
1810
0
          memcpy(new_buf+offset, part->headers.s , part->headers.len);
1811
0
          offset += part->headers.len ;
1812
0
          memcpy(new_buf+offset, CRLF , CRLF_LEN);
1813
0
          offset += CRLF_LEN;
1814
0
        }
1815
        /* simply copy the body of the part */
1816
0
        if (part->dump_f) {
1817
0
          memcpy(new_buf+offset, part->dump.s, part->dump.len );
1818
0
          offset += part->dump.len;
1819
0
          part->dump.s = NULL;
1820
0
          part->dump.len = 0;
1821
0
        } else {
1822
0
          memcpy(new_buf+offset, part->body.s, part->body.len );
1823
0
          offset += part->body.len;
1824
0
        }
1825
0
        memcpy(new_buf+offset, CRLF , CRLF_LEN);
1826
0
        offset += CRLF_LEN;
1827
0
      } else
1828
      /* old part with dump function */
1829
0
      if (part->dump_f) {
1830
        /* copy separator and headers from original message */
1831
0
        size = (part->body.s - msg->buf) - *orig_offs;
1832
0
        memcpy( new_buf+offset,  msg->buf+*orig_offs, size);
1833
0
        offset += size;
1834
        /* put in the new body */
1835
0
        memcpy(new_buf+offset, part->dump.s, part->dump.len );
1836
0
        offset += part->dump.len;
1837
0
        pkg_free(part->dump.s);
1838
0
        part->dump.s = NULL;
1839
0
        part->dump.len = 0;
1840
0
        memcpy(new_buf+offset, CRLF , CRLF_LEN);
1841
0
        offset += CRLF_LEN;
1842
0
      } else
1843
      /* old part with lumps -> apply changes */
1844
0
      {
1845
        /* first find the first lump inside our body part
1846
         * NOTE: we do not need to explicitly copy the separtor and
1847
         * the headers as they will be automatically got by the 
1848
         * first lup or by the final copy */
1849
0
        while ( lump && lump->u.offset<(part->body.s-msg->buf) )
1850
0
          lump=lump->next;
1851
0
        if (lump) {
1852
0
          LM_DBG("lumps found in the part, applying...\n");
1853
          /* apply the lumps */
1854
0
          process_lumps( msg, lump, new_buf, &offset, orig_offs,
1855
0
            send_sock, part->body.s+part->body.len-msg->buf);
1856
0
        }
1857
        /* and copy whatever is left, all the way to the end of part,
1858
         * including the next CRLF */
1859
0
        size = (part->body.s+part->body.len-msg->buf+CRLF_LEN)-*orig_offs;
1860
0
        memcpy(new_buf+offset, msg->buf+*orig_offs, size);
1861
0
        offset += size;
1862
0
      }
1863
1864
      /* reposition at the end of the processed body */
1865
0
      if ((part->flags & SIP_BODY_PART_FLAG_NEW) == 0)
1866
0
        *orig_offs = part->body.s+part->body.len-msg->buf+CRLF_LEN;
1867
1868
0
    } /* end for(over the parts) */
1869
1870
    /* the final separator */
1871
0
    size = msg->len - *orig_offs;
1872
0
    memcpy(new_buf+offset, msg->buf+*orig_offs , size);
1873
0
    *new_offs = offset + size;
1874
0
    *orig_offs += size;
1875
1876
0
  }
1877
125
  return;
1878
125
}
1879
1880
1881
/* Calculated the body difference in lenght after applying
1882
 *   all the changes (over the sip body) !
1883
 * This is a wrapper to hide the differences between 
1884
 *   lump-based changes and body_part-based changes.
1885
 */
1886
static inline int calculate_body_diff(struct sip_msg *msg,
1887
                          const struct socket_info *sock )
1888
11.7k
{
1889
11.7k
  str body, rcv_body = STR_NULL;
1890
11.7k
  struct sdp_body_part_ops *ops;
1891
1892
11.7k
  if (have_sdp_ops(msg)) {
1893
0
    if (get_body(msg, &body) != 0 || body.len==0)
1894
0
      return 0;
1895
1896
0
    ops = msg->sdp_ops;
1897
0
    msg->sdp_ops = NULL;
1898
0
    get_body(msg, &rcv_body);
1899
0
    msg->sdp_ops = ops;
1900
1901
0
    return body.len - rcv_body.len;
1902
0
  }
1903
1904
11.7k
  if (msg->body==NULL) {
1905
    /* no body parsed, no advanced ops done, just dummy lumps over body */
1906
11.6k
    return lumps_len(msg, msg->body_lumps, sock, -1);
1907
11.6k
  } else {
1908
125
    return ((int)prep_reassemble_body_parts( msg, sock) - msg->body->body.len);
1909
125
  }
1910
11.7k
}
1911
1912
1913
/* Writes down the new SIP message buffer (SIP headers and body) after
1914
 *   after applying all the changes (over SIP hdrs and SIP body) !
1915
 * This is a wrapper to hide the differences between 
1916
 *   lump-based changes and body_part-based changes.
1917
 */
1918
static inline void apply_msg_changes(struct sip_msg *msg,
1919
              char *new_buf, unsigned int *new_offs,
1920
              unsigned int *orig_offs, const struct socket_info *sock,
1921
              unsigned int max_offset)
1922
11.7k
{
1923
11.7k
  unsigned int size;
1924
11.7k
  str body;
1925
1926
  /* apply changes over the SIP headers */
1927
11.7k
  process_lumps(msg, msg->add_rm, new_buf, new_offs, orig_offs, sock, -1);
1928
1929
  /* real-time SDP changes */
1930
11.7k
  if (have_sdp_ops(msg)) {
1931
0
    if (get_body(msg, &body) != 0 || body.len==0)
1932
0
      return;
1933
1934
0
    size = msg->body->body.s ?
1935
0
      ((msg->body->body.s - msg->buf) - *orig_offs)  /* msg had body */
1936
0
      : (msg->len - *orig_offs);                     /* no body at all */
1937
0
    memcpy(new_buf+*new_offs, msg->buf+*orig_offs, size );
1938
0
    *new_offs += size;
1939
0
    *orig_offs += size;
1940
1941
0
    memcpy(new_buf+*new_offs, body.s, body.len);
1942
0
    *new_offs += body.len;
1943
0
    return;
1944
0
  }
1945
1946
  /* lumps-based SDP changes */
1947
11.7k
  if (msg->body==NULL) {
1948
    /* no body parsed, no advanced ops done, just dummy lumps over body */
1949
11.6k
    process_lumps(msg, msg->body_lumps, new_buf, new_offs,
1950
11.6k
      orig_offs, sock, max_offset);
1951
    /* copy the rest of the message */
1952
11.6k
    memcpy(new_buf+*new_offs, msg->buf+*orig_offs, max_offset-*orig_offs);
1953
11.6k
    *new_offs += max_offset-*orig_offs;
1954
11.6k
  } else {
1955
    /* copy whatever is left in the original buffer (up to the body) */
1956
125
    size = msg->body->body.s ?
1957
125
      ((msg->body->body.s - msg->buf) - *orig_offs)  /* msg had body */
1958
125
      : (msg->len - *orig_offs);                     /* no body at all */
1959
125
    memcpy(new_buf+*new_offs, msg->buf+*orig_offs, size );
1960
125
    *new_offs += size;
1961
125
    *orig_offs += size;
1962
    /* rebuild the body, part by part, in a content wise manner */
1963
125
    reassemble_body_parts(msg, new_buf, new_offs, orig_offs, sock);
1964
125
  }
1965
11.7k
}
1966
1967
1968
/*! \brief
1969
 * Adjust/insert Content-Length if necessary
1970
 */
1971
static inline int adjust_clen(struct sip_msg* msg, int body_delta, int proto)
1972
11.7k
{
1973
11.7k
  struct lump* anchor;
1974
11.7k
  char* clen_buf;
1975
11.7k
  int clen_len;
1976
1977
  /* Calculate message length difference caused by lumps modifying message
1978
   * body, from this point on the message body must not be modified. Zero
1979
   * value indicates that the body hasn't been modified
1980
  */
1981
1982
11.7k
  clen_buf = 0;
1983
11.7k
  anchor=0;
1984
1985
  /* check to see if we need to add clen */
1986
11.7k
  if (is_tcp_based_proto(proto)) {
1987
0
    if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1){
1988
0
      LM_ERR("parsing content-length\n");
1989
0
      goto error;
1990
0
    }
1991
0
    if (msg->content_length==0){
1992
      /* not present, we need to add it */
1993
      /* msg->unparsed should point just before the final crlf
1994
       * - whole message was parsed by the above parse_headers
1995
       *   which did not find content-length */
1996
0
      anchor=anchor_lump(msg, msg->unparsed-msg->buf,
1997
0
                        HDR_CONTENTLENGTH_T);
1998
0
      if (anchor==0){
1999
0
        LM_ERR("cannot set clen anchor\n");
2000
0
        goto error;
2001
0
      }
2002
0
    }
2003
0
  }
2004
2005
11.7k
  if ((anchor==0) && body_delta){
2006
0
    if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) {
2007
0
      LM_ERR("parsing Content-Length\n");
2008
0
      goto error;
2009
0
    }
2010
2011
    /* The body has been changed, try to find
2012
     * existing Content-Length
2013
     */
2014
    /* no need for Content-Length if it's and UDP packet and
2015
     * it hasn't Content-Length already */
2016
0
    if (msg->content_length==0){
2017
        /* content-length doesn't exist, append it */
2018
      /* msg->unparsed should point just before the final crlf
2019
       * - whole message was parsed by the above parse_headers
2020
       *   which did not find content-length */
2021
0
      if (proto!=PROTO_UDP){
2022
0
        anchor=anchor_lump(msg, msg->unparsed-msg->buf,
2023
0
                          HDR_CONTENTLENGTH_T);
2024
0
        if (anchor==0){
2025
0
          LM_ERR("cannot set clen anchor\n");
2026
0
          goto error;
2027
0
        }
2028
0
      }else{
2029
0
        LM_DBG("the UDP packet has no clen => not adding one \n");
2030
0
      }
2031
0
    }else{
2032
      /* Content-Length has been found, remove it */
2033
0
      anchor = del_lump(  msg, msg->content_length->name.s - msg->buf,
2034
0
                msg->content_length->len, HDR_CONTENTLENGTH_T);
2035
0
      if (anchor==0) {
2036
0
        LM_ERR("can't remove original Content-Length\n");
2037
0
        goto error;
2038
0
      }
2039
0
    }
2040
0
  }
2041
2042
11.7k
  if (anchor){
2043
0
    clen_buf = clen_builder(msg, &clen_len, body_delta);
2044
0
    if (!clen_buf) goto error;
2045
0
    if (insert_new_lump_after(anchor, clen_buf, clen_len,
2046
0
          HDR_CONTENTLENGTH_T) == 0)
2047
0
      goto error;
2048
0
  }
2049
2050
11.7k
  return 0;
2051
0
error:
2052
0
  if (clen_buf) pkg_free(clen_buf);
2053
0
  return -1;
2054
11.7k
}
2055
2056
2057
/*! \brief
2058
 * Save given Path body as Route header in message.
2059
 *
2060
 * If another Route HF is found, it's placed right before that.
2061
 * Otherwise, it's placed after the last Via HF. If also no
2062
 * Via HF is found, it's placed as first HF.
2063
 */
2064
0
#define ROUTE_STR  "Route: "
2065
0
#define ROUTE_LEN  (sizeof(ROUTE_STR)-1)
2066
static inline int insert_path_as_route(struct sip_msg* msg, str* path)
2067
0
{
2068
0
  struct lump *anchor;
2069
0
  char *route;
2070
0
  struct hdr_field *hf, *last_via=0;
2071
2072
0
  for (hf = msg->headers; hf; hf = hf->next) {
2073
0
    if (hf->type == HDR_ROUTE_T) {
2074
0
      break;
2075
0
    } else if (hf->type == HDR_VIA_T) {
2076
0
      last_via = hf;
2077
0
    }
2078
0
  }
2079
0
  if (hf) {
2080
    /* Route HF found, insert before it */
2081
0
    anchor = anchor_lump(msg, hf->name.s - msg->buf, 0);
2082
0
  } else if(last_via) {
2083
0
    if (last_via->next) {
2084
      /* Via HF in between, insert after it */
2085
0
      anchor = anchor_lump(msg, last_via->next->name.s - msg->buf, 0);
2086
0
    } else {
2087
      /* Via HF is last, so append */
2088
0
      anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0);
2089
0
    }
2090
0
  } else {
2091
    /* None of the above, insert as first */
2092
0
    anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0);
2093
0
  }
2094
2095
0
  if (anchor == 0) {
2096
0
    LM_ERR("failed to get anchor\n");
2097
0
    return -1;
2098
0
  }
2099
2100
0
  route = pkg_malloc(ROUTE_LEN + path->len + CRLF_LEN);
2101
0
  if (!route) {
2102
0
    LM_ERR("out of pkg memory\n");
2103
0
    return -1;
2104
0
  }
2105
0
  memcpy(route, ROUTE_STR, ROUTE_LEN);
2106
0
  memcpy(route + ROUTE_LEN, path->s, path->len);
2107
0
  memcpy(route + ROUTE_LEN + path->len, CRLF, CRLF_LEN);
2108
2109
0
  if (insert_new_lump_before(anchor, route, ROUTE_LEN + path->len + CRLF_LEN, 0) == 0) {
2110
0
    LM_ERR("failed to insert lump\n");
2111
0
    return -1;
2112
0
  }
2113
2114
0
  msg->msg_flags |= FL_HAS_ROUTE_LUMP;
2115
2116
0
  return 0;
2117
0
}
2118
2119
int is_del_via1_lump(struct sip_msg* msg)
2120
11.7k
{
2121
11.7k
  struct lump* lump;
2122
11.7k
  int via1_off, via1_len;
2123
2124
/*  for(lump= msg->add_rm; lump; lump= lump->next)
2125
    if(lump->type == HDR_VIA1_T && lump->op== LUMP_DEL)
2126
      return 1;
2127
*/
2128
11.7k
  if(!msg->h_via1)
2129
0
    return 0;
2130
2131
11.7k
  via1_off = msg->h_via1->name.s - msg->buf;
2132
11.7k
  via1_len = msg->h_via1->len;
2133
2134
11.7k
  for(lump= msg->add_rm; lump; lump= lump->next)
2135
0
  {
2136
0
    if(lump->type == 0 && lump->op== LUMP_DEL && lump->u.offset == via1_off && lump->len == via1_len)
2137
0
      return 1;
2138
0
  }
2139
11.7k
  return 0;
2140
11.7k
}
2141
2142
char * build_req_buf_from_sip_req( struct sip_msg* msg,
2143
                unsigned int *returned_len,
2144
                const struct socket_info* send_sock, int proto,
2145
                str *via_params, unsigned int flags)
2146
11.7k
{
2147
11.7k
  unsigned int len, new_len, received_len, rport_len, uri_len, via_len, body_delta;
2148
11.7k
  char *line_buf, *received_buf, *rport_buf, *new_buf, *buf, *id_buf;
2149
11.7k
  unsigned int offset, s_offset, size, id_len;
2150
11.7k
  struct lump *anchor, *via_insert_param;
2151
11.7k
  str branch, extra_params, body = STR_NULL;
2152
11.7k
  struct hostport hp;
2153
2154
11.7k
  id_buf=0;
2155
11.7k
  id_len=0;
2156
11.7k
  via_insert_param=0;
2157
11.7k
  extra_params.len=0;
2158
11.7k
  extra_params.s=0;
2159
11.7k
  uri_len=0;
2160
11.7k
  buf=msg->buf;
2161
11.7k
  len=msg->len;
2162
11.7k
  received_len=0;
2163
11.7k
  rport_len=0;
2164
11.7k
  new_buf=0;
2165
11.7k
  received_buf=0;
2166
11.7k
  rport_buf=0;
2167
11.7k
  line_buf=0;
2168
11.7k
  int via1_deleted = 0;
2169
2170
11.7k
  if (msg->path_vec.len) {
2171
0
    if (insert_path_as_route(msg, &msg->path_vec) < 0) {
2172
0
      LM_ERR("adding path lumps failed\n");
2173
0
      goto error;
2174
0
    }
2175
0
  }
2176
2177
  /* Calculate message body difference and adjust
2178
   * Content-Length
2179
   */
2180
11.7k
  body_delta = calculate_body_diff( msg, send_sock);
2181
11.7k
  if (adjust_clen(msg, body_delta, proto) < 0) {
2182
0
    LM_ERR("failed to adjust Content-Length\n");
2183
0
    goto error;
2184
0
  }
2185
2186
11.7k
  if (flags&MSG_TRANS_NOVIA_FLAG)
2187
0
    goto build_msg;
2188
2189
  /* add id if tcp-based protocol  */
2190
11.7k
  if (is_tcp_based_proto(msg->rcv.proto)) {
2191
0
    if  ((id_buf=id_builder(msg, &id_len))==0){
2192
0
      LM_ERR("id_builder failed\n");
2193
0
      goto error; /* we don't need to free anything,
2194
                       nothing alloc'ed yet*/
2195
0
    }
2196
0
    LM_DBG("id added: <%.*s>, rcv proto=%d\n",
2197
0
        (int)id_len, id_buf, msg->rcv.proto);
2198
    /* if there was already something there, simply copy them */
2199
0
    if (via_params && via_params->len != 0) {
2200
0
      extra_params.len = id_len + via_params->len;
2201
0
      extra_params.s=pkg_malloc(extra_params.len);
2202
0
      if(extra_params.s==0) {
2203
0
        LM_ERR("extra params building failed\n");
2204
0
        pkg_free(id_buf);
2205
0
        goto error;
2206
0
      }
2207
0
      memcpy(extra_params.s, via_params->s, via_params->len);
2208
0
      memcpy(extra_params.s + via_params->len, id_buf, id_len);
2209
0
      pkg_free(id_buf);
2210
0
    } else {
2211
0
      extra_params.s=id_buf;
2212
0
      extra_params.len=id_len;
2213
0
    }
2214
0
  }
2215
2216
  /* check whether to add rport parameter to local via */
2217
11.7k
  if(msg->msg_flags&FL_FORCE_LOCAL_RPORT) {
2218
5.49k
    id_buf=extra_params.s;
2219
5.49k
    id_len=extra_params.len;
2220
5.49k
    if (via_params && !extra_params.len) {
2221
      /* if no other parameters were added yet, consider via_params */
2222
0
      extra_params.len = via_params->len;
2223
      /* otherwise, the via_params were already copied in the id block */
2224
0
    }
2225
5.49k
    extra_params.len += RPORT_LEN-1; /* last char in RPORT define is '='
2226
                    which is not added, but the new buffer
2227
                    will be null terminated */
2228
5.49k
    extra_params.s = (char*)pkg_malloc(extra_params.len+1);
2229
5.49k
    if(extra_params.s==0) {
2230
0
      LM_ERR("extra params building failed\n");
2231
0
      if (id_buf) pkg_free(id_buf);
2232
0
      goto error;
2233
0
    }
2234
2235
5.49k
    if(id_buf!=0) {
2236
0
      memcpy(extra_params.s, id_buf, id_len);
2237
0
      pkg_free(id_buf);
2238
5.49k
    } else if (via_params) {
2239
0
      memcpy(extra_params.s, via_params->s, via_params->len);
2240
0
      id_len = via_params->len;
2241
0
    }
2242
5.49k
    memcpy(extra_params.s+id_len, RPORT, RPORT_LEN-1);
2243
5.49k
    extra_params.s[extra_params.len]='\0';
2244
5.49k
    LM_DBG("extra param added: <%.*s>\n",extra_params.len, extra_params.s);
2245
5.49k
  }
2246
2247
11.7k
  branch.s=msg->add_to_branch_s;
2248
11.7k
  branch.len=msg->add_to_branch_len;
2249
11.7k
  set_hostport(&hp, msg);
2250
11.7k
  line_buf = via_builder( &via_len, send_sock, &branch,
2251
11.7k
            extra_params.len?&extra_params:via_params, proto, &hp);
2252
11.7k
  if (!line_buf){
2253
0
    LM_ERR("no via received!\n");
2254
0
    goto error00;
2255
0
  }
2256
2257
11.7k
  via1_deleted = is_del_via1_lump(msg);
2258
  /* check if received needs to be added:
2259
   *  - if the VIA address and the received address are different
2260
   *  - if the rport was forced (rport requires received)
2261
   *  - if the rport was received in the VIA hdr
2262
   *  - and there is no lump that delets VIA1 hdr */
2263
11.7k
  if ( (msg->via1->rport || (msg->msg_flags&FL_FORCE_RPORT) ||
2264
11.7k
      received_test(msg) ) && !via1_deleted) {
2265
11.7k
    if ((received_buf=received_builder(msg,&received_len))==0){
2266
0
      LM_ERR("received_builder failed\n");
2267
0
      goto error01;  /* free also line_buf */
2268
0
    }
2269
11.7k
  }
2270
2271
  /* check if rport needs to be updated:
2272
   *  - if FL_FORCE_RPORT is set add it (and del. any previous version)
2273
   *  - if via already contains an rport add it and overwrite the previous
2274
   *  rport value if present (if you don't want to overwrite the previous
2275
   *  version remove the comments) */
2276
11.7k
  if (((msg->msg_flags&FL_FORCE_RPORT)||
2277
6.18k
      (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)) && !via1_deleted){
2278
6.18k
    if ((rport_buf=rport_builder(msg, &rport_len))==0){
2279
0
      LM_ERR("rport_builder failed\n");
2280
0
      goto error01; /* free everything */
2281
0
    }
2282
6.18k
  }
2283
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
11.7k
  anchor=anchor_lump(msg, msg->via1->hdr.s-buf, HDR_VIA_T);
2288
11.7k
  if (anchor==0) goto error01;
2289
11.7k
  if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA_T)==0)
2290
0
    goto error01;
2291
  /* find out where the offset of the first parameter that should be added
2292
   * (after host:port), needed by add receive & maybe rport */
2293
11.7k
  if (msg->via1->params.s){
2294
230
      size= msg->via1->params.s-msg->via1->hdr.s-1; /*compensate
2295
                              for ';' */
2296
11.5k
  }else{
2297
11.5k
      size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
2298
11.5k
      if (msg->via1->port!=0){
2299
        /*size+=strlen(msg->via1->hdr.s+size+1)+1;*/
2300
39
        size += msg->via1->port_str.len + 1; /* +1 for ':'*/
2301
39
      }
2302
11.5k
  }
2303
  /* if received needs to be added, add anchor after host and add it, or
2304
   * overwrite the previous one if already present */
2305
11.7k
  if (received_len){
2306
11.7k
    if (msg->via1->received){ /* received already present => overwrite it*/
2307
52
      via_insert_param=del_lump(msg,
2308
52
                msg->via1->received->start-buf-1, /*;*/
2309
52
                msg->via1->received->size+1, /*;*/ HDR_VIA_T);
2310
11.7k
    }else if (via_insert_param==0){ /* receive not present, ok */
2311
11.7k
      via_insert_param=anchor_lump(msg,
2312
11.7k
                    msg->via1->hdr.s-buf+size, HDR_VIA_T);
2313
11.7k
    }
2314
11.7k
    if (via_insert_param==0) goto error02; /* free received_buf */
2315
11.7k
    if (insert_new_lump_after(via_insert_param, received_buf, received_len,
2316
11.7k
          HDR_VIA_T) ==0 ) goto error02; /* free received_buf */
2317
11.7k
  }
2318
  /* if rport needs to be updated, delete it if present and add it's value */
2319
11.7k
  if (rport_len){
2320
6.18k
    if (msg->via1->rport){ /* rport already present */
2321
65
      via_insert_param=del_lump(msg,
2322
65
                msg->via1->rport->start-buf-1, /*';'*/
2323
65
                msg->via1->rport->size+1 /* ; */, HDR_VIA_T);
2324
6.11k
    }else if (via_insert_param==0){ /*force rport, no rport present */
2325
      /* no rport, add it */
2326
0
      via_insert_param=anchor_lump(msg,
2327
0
                  msg->via1->hdr.s-buf+size, HDR_VIA_T);
2328
0
    }
2329
6.18k
    if (via_insert_param==0) goto error03; /* free rport_buf */
2330
6.18k
    if (insert_new_lump_after(via_insert_param, rport_buf, rport_len,
2331
6.18k
                  HDR_VIA_T) ==0 )
2332
0
      goto error03; /* free rport_buf */
2333
6.18k
  }
2334
2335
11.7k
build_msg:
2336
  /* adjust len to the useful part of the message */
2337
11.7k
  if (!have_sdp_ops(msg) && get_body(msg, &body) == 0 && body.len)
2338
473
    len -= (msg->buf + msg->len - body.s - body.len);
2339
2340
  /* compute new msg len and fix overlapping zones*/
2341
11.7k
  new_len=len+body_delta+lumps_len(msg, msg->add_rm, send_sock,-1);
2342
#ifdef XL_DEBUG
2343
  LM_DBG("new_len(%d)=len(%d)+lumps_len\n", new_len, len);
2344
#endif
2345
2346
11.7k
  if (msg->new_uri.s){
2347
0
    uri_len=msg->new_uri.len;
2348
0
    new_len=new_len-msg->first_line.u.request.uri.len+uri_len;
2349
0
  }
2350
11.7k
  if (flags&MSG_TRANS_SHM_FLAG)
2351
0
    new_buf=(char*)shm_malloc(new_len+1);
2352
11.7k
  else
2353
11.7k
    new_buf=(char*)pkg_malloc(new_len+1);
2354
11.7k
  if (new_buf==0){
2355
0
    ser_error=E_OUT_OF_MEM;
2356
0
    LM_ERR("out of pkg memory\n");
2357
0
    goto error00;
2358
0
  }
2359
2360
11.7k
  offset=s_offset=0;
2361
11.7k
  if (msg->new_uri.s){
2362
    /* copy message up to uri */
2363
0
    size=msg->first_line.u.request.uri.s-buf;
2364
0
    memcpy(new_buf, buf, size);
2365
0
    offset+=size;
2366
0
    s_offset+=size;
2367
    /* add our uri */
2368
0
    memcpy(new_buf+offset, msg->new_uri.s, uri_len);
2369
0
    offset+=uri_len;
2370
0
    s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */
2371
0
  }
2372
2373
  /* apply changes over SIP hdrs and body */
2374
11.7k
  apply_msg_changes( msg, new_buf, &offset, &s_offset, send_sock, len);
2375
11.7k
  if (offset!=new_len) {
2376
0
    LM_BUG("len mismatch : calculated %d, written %d\n", new_len, offset);
2377
0
    abort();
2378
0
  }
2379
2380
11.7k
  new_buf[new_len]=0;
2381
2382
11.7k
  *returned_len=new_len;
2383
  /* cleanup */
2384
11.7k
  if (extra_params.s) pkg_free(extra_params.s);
2385
11.7k
  return new_buf;
2386
2387
0
error01:
2388
0
  if (line_buf) pkg_free(line_buf);
2389
0
error02:
2390
0
  if (received_buf) pkg_free(received_buf);
2391
0
error03:
2392
0
  if (rport_buf) pkg_free(rport_buf);
2393
0
error00:
2394
0
  if (extra_params.s) pkg_free(extra_params.s);
2395
0
error:
2396
0
  *returned_len=0;
2397
0
  return 0;
2398
0
}
2399
2400
2401
2402
char * build_res_buf_from_sip_res( struct sip_msg* msg,
2403
  unsigned int *returned_len, const struct socket_info *sock,int flags)
2404
0
{
2405
0
  unsigned int new_len, body_delta, len;
2406
0
  char *new_buf, *buf;
2407
0
  unsigned int offset, s_offset;
2408
0
  str body;
2409
2410
0
  buf=msg->buf;
2411
0
  len=msg->len;
2412
0
  new_buf=0;
2413
2414
  /* Calculate message body difference and adjust
2415
   * Content-Length
2416
   */
2417
0
  body_delta = calculate_body_diff( msg, sock);
2418
0
  if (adjust_clen(msg, body_delta, (msg->via2? msg->via2->proto:PROTO_UDP))
2419
0
      < 0) {
2420
0
    LM_ERR("failed to adjust Content-Length\n");
2421
0
    goto error;
2422
0
  }
2423
2424
  /* remove the first via */
2425
0
  if (!(flags & MSG_TRANS_NOVIA_FLAG)) {
2426
0
    unsigned int via_len, via_offset;
2427
2428
0
    if (msg->via1->next) {
2429
0
      via_len = msg->via1->bsize;
2430
0
      via_offset = msg->h_via1->body.s-buf;
2431
0
    } else {
2432
0
      via_len = msg->h_via1->len;
2433
0
      via_offset = msg->h_via1->name.s-buf;
2434
0
    }
2435
2436
0
    if (del_lump(msg, via_offset, via_len, HDR_VIA_T) == 0) {
2437
0
      LM_ERR("failed to remove first via\n");
2438
0
      goto error;
2439
0
    }
2440
0
  }
2441
2442
  /* adjust len to the useful part of the message */
2443
0
  if (get_body(msg, &body) == 0 && body.len)
2444
0
    len -= (msg->buf + msg->len - body.s - body.len);
2445
0
  new_len=len+body_delta+lumps_len(msg, msg->add_rm, sock, -1);
2446
2447
0
  LM_DBG(" old size: %d, new size: %d\n", len, new_len);
2448
0
  new_buf=(char*)pkg_malloc(new_len+1); /* +1 is for debugging
2449
                       (\0 to print it )*/
2450
0
  if (new_buf==0){
2451
0
    LM_ERR("out of pkg mem\n");
2452
0
    goto error;
2453
0
  }
2454
0
  offset=s_offset=0;
2455
2456
  /* apply changes over SIP hdrs and body */
2457
0
  apply_msg_changes( msg, new_buf, &offset, &s_offset, sock, len);
2458
0
  if (offset!=new_len) {
2459
0
    LM_BUG("len mismatch : calculated %d, written %d\n", new_len, offset);
2460
0
    abort();
2461
0
  }
2462
2463
0
  new_buf[new_len]=0; /* debug: print the message */
2464
2465
  /* as it is a relaied reply, if 503, make it 500 (just reply code) */
2466
0
  if ( !disable_503_translation && msg->first_line.u.reply.statuscode==503 )
2467
0
    new_buf[(int)(msg->first_line.u.reply.status.s-msg->buf)+2] = '0';
2468
  /* send it! */
2469
0
  LM_DBG("copied size: orig:%d, new: %d, rest: %d"
2470
0
      " msg=|\n%s|\n", s_offset, offset, len-s_offset, new_buf);
2471
2472
0
  *returned_len=new_len;
2473
0
  return new_buf;
2474
0
error:
2475
0
  *returned_len=0;
2476
0
  return 0;
2477
0
}
2478
2479
2480
char * build_res_buf_from_sip_req( unsigned int code, const str *text ,str *new_tag,
2481
    struct sip_msg* msg, unsigned int *returned_len, struct bookmark *bmark)
2482
0
{
2483
0
  char *buf, *p, *received_buf, *rport_buf, *warning_buf;
2484
0
  char *content_len_buf, *after_body, *totags;
2485
0
  unsigned int len, foo, received_len, rport_len;
2486
0
  unsigned int warning_len, content_len_len;
2487
0
  struct hdr_field *hdr;
2488
0
  struct lump_rpl *lump, *body;
2489
0
  int i;
2490
0
  str to_tag;
2491
2492
0
  body = 0;
2493
0
  buf=0;
2494
0
  to_tag.s = 0;
2495
0
  to_tag.len = 0;
2496
0
  received_buf=rport_buf=warning_buf=content_len_buf=0;
2497
0
  received_len=rport_len=warning_len=content_len_len=0;
2498
2499
  /* force parsing all headers -- we want to return all
2500
  Via's in the reply and they may be scattered down to the
2501
  end of header (non-block Vias are a really poor property
2502
  of SIP :( ) */
2503
0
  if (parse_headers( msg, HDR_EOH_F, 0 )==-1) {
2504
0
    LM_ERR("parse_headers failed\n");
2505
0
    goto error00;
2506
0
  }
2507
2508
  /*computes the length of the new response buffer*/
2509
0
  len = 0;
2510
2511
  /* check if rport needs to be updated */
2512
0
  if ( (msg->msg_flags&FL_FORCE_RPORT)||
2513
0
    (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)){
2514
0
    if ((rport_buf=rport_builder(msg, &rport_len))==0){
2515
0
      LM_ERR("rport_builder failed\n");
2516
0
      goto error00;
2517
0
    }
2518
0
    if (msg->via1->rport)
2519
0
      len -= msg->via1->rport->size+1; /* include ';' */
2520
0
  }
2521
2522
  /* check if received needs to be added or via rport has to be added */
2523
0
  if (rport_buf || received_test(msg)) {
2524
0
    if ((received_buf=received_builder(msg,&received_len))==0) {
2525
0
      LM_ERR("received_builder failed\n");
2526
0
      goto error01;
2527
0
    }
2528
0
  }
2529
2530
  /* first line */
2531
0
  len += SIP_VERSION_LEN + 1/*space*/ + 3/*code*/ + 1/*space*/ +
2532
0
    text->len + CRLF_LEN/*new line*/;
2533
  /* copy the TO hdr */
2534
0
  if (msg->to) {
2535
0
    if (new_tag && new_tag->len) {
2536
0
      to_tag=get_to(msg)->tag_value;
2537
0
      if (to_tag.len )
2538
0
        len+=new_tag->len-to_tag.len;
2539
0
      else
2540
0
        len+=new_tag->len+TOTAG_TOKEN_LEN/*";tag="*/;
2541
0
    }
2542
0
    len += msg->to->len;
2543
0
  }
2544
2545
  /* copy all VIA hdrs */
2546
0
  for( hdr=msg->h_via1 ; hdr ; hdr=hdr->sibling) {
2547
    /* we always add CRLF to via*/
2548
0
    len+=(hdr->body.s+hdr->body.len)-hdr->name.s+CRLF_LEN;
2549
0
    if (hdr==msg->h_via1) len += received_len+rport_len;
2550
0
  }
2551
  /* copy all Record-Route hdrs */
2552
0
  for( hdr=msg->record_route ; hdr ; hdr=hdr->sibling) {
2553
    /* RR only for 1xx and 2xx replies */
2554
0
    if (code>=180 && code<300)
2555
0
      len += hdr->len;
2556
0
  }
2557
  /* copy the FROM hdr */
2558
0
  if (msg->from)
2559
0
    len += msg->from->len;
2560
  /* copy the CALLID hdr */
2561
0
  if (msg->callid)
2562
0
    len += msg->callid->len;
2563
  /* copy the CSEQ hdr */
2564
0
  if (msg->cseq)
2565
0
    len += msg->cseq->len;
2566
2567
  /* lumps length */
2568
0
  for(lump=msg->reply_lump;lump;lump=lump->next) {
2569
0
    len += lump->text.len;
2570
0
    if (lump->flags&LUMP_RPL_BODY)
2571
0
      body = lump;
2572
0
  }
2573
  /* server header */
2574
0
  if (server_signature)
2575
0
    len += server_header->len + CRLF_LEN;
2576
  /* warning hdr */
2577
0
  if (sip_warning) {
2578
0
    warning_buf = warning_builder(msg,&warning_len);
2579
0
    if (warning_buf) len += warning_len + CRLF_LEN;
2580
0
    else LM_WARN("warning skipped -- too big\n");
2581
0
  }
2582
  /* content length hdr */
2583
0
  if (body) {
2584
0
    content_len_buf = int2str(body->text.len, (int*)&content_len_len);
2585
0
    len += CONTENT_LENGTH_LEN + content_len_len + CRLF_LEN;
2586
0
  } else {
2587
0
    len += CONTENT_LENGTH_LEN + 1/*0*/ + CRLF_LEN;
2588
0
  }
2589
  /* end of message */
2590
0
  len += CRLF_LEN; /*new line*/
2591
2592
  /*allocating mem*/
2593
0
  buf = (char*) pkg_malloc( len+1 );
2594
0
  if (!buf)
2595
0
  {
2596
0
    LM_ERR("out of pkg memory; needs %d\n",len);
2597
0
    goto error01;
2598
0
  }
2599
2600
  /* filling the buffer*/
2601
0
  p=buf;
2602
  /* first line */
2603
0
  memcpy( p , SIP_VERSION , SIP_VERSION_LEN );
2604
0
  p += SIP_VERSION_LEN;
2605
0
  *(p++) = ' ' ;
2606
  /*code*/
2607
0
  for ( i=2 , foo = code  ;  i>=0  ;  i-- , foo=foo/10 )
2608
0
    *(p+i) = '0' + foo - ( foo/10 )*10;
2609
0
  p += 3;
2610
0
  *(p++) = ' ' ;
2611
0
  memcpy( p , text->s , text->len );
2612
0
  p += text->len;
2613
0
  memcpy( p, CRLF, CRLF_LEN );
2614
0
  p+=CRLF_LEN;
2615
  /* VIA headers */
2616
0
  if ( (hdr=msg->h_via1)!=NULL ) {
2617
    /* handle the VIA1, subject to changes */
2618
0
    i = 0;
2619
0
    if (received_buf) {
2620
0
      i = msg->via1->host.s - msg->via1->hdr.s +
2621
0
        msg->via1->host.len + (msg->via1->port?
2622
0
        msg->via1->port_str.len + 1 : 0);
2623
      /* copy via1 up to params */
2624
0
      append_str( p, hdr->name.s, i);
2625
      /* copy received param */
2626
0
      append_str( p, received_buf, received_len);
2627
0
    }
2628
0
    if (rport_buf){
2629
0
      if (msg->via1->rport){ /* delete the old one */
2630
        /* copy until rport */
2631
0
        append_str( p, hdr->name.s+i ,
2632
0
          msg->via1->rport->start-hdr->name.s-1-i);
2633
        /* copy new rport */
2634
0
        append_str(p, rport_buf, rport_len);
2635
        /* copy the rest of the via */
2636
0
        append_str(p, msg->via1->rport->start+
2637
0
                  msg->via1->rport->size,
2638
0
                  hdr->body.s+hdr->body.len-
2639
0
                  msg->via1->rport->start-
2640
0
                  msg->via1->rport->size);
2641
0
      }else{ /* just copy rport and rest of hdr */
2642
0
        append_str(p, rport_buf, rport_len);
2643
0
        append_str( p, hdr->name.s+i ,
2644
0
          (hdr->body.s+hdr->body.len)-hdr->name.s-i);
2645
0
      }
2646
0
    }else{
2647
      /* normal whole via copy */
2648
0
      append_str( p, hdr->name.s+i ,
2649
0
        (hdr->body.s+hdr->body.len)-hdr->name.s-i);
2650
0
    }
2651
0
    append_str( p, CRLF,CRLF_LEN);
2652
    /* and now the rest of the VIA hdrs */
2653
0
    for( hdr=hdr->sibling ; hdr ; hdr=hdr->sibling) {
2654
      /* normal whole via copy */
2655
0
      append_str( p, hdr->name.s,
2656
0
          (hdr->body.s+hdr->body.len)-hdr->name.s);
2657
0
      append_str( p, CRLF,CRLF_LEN);
2658
0
    }
2659
0
  }
2660
  /* Record-Route headers */
2661
0
  for( hdr=msg->record_route ; hdr ; hdr=hdr->sibling) {
2662
    /* RR only for 1xx and 2xx replies */
2663
0
    if (code>=180 && code<300)
2664
0
      append_str(p, hdr->name.s, hdr->len);
2665
0
  }
2666
  /* TO hdr */
2667
0
  if ( (hdr=msg->to)!=NULL ) {
2668
0
    if (new_tag && new_tag->len){
2669
0
      if (to_tag.len ) { /* replacement */
2670
        /* before to-tag */
2671
0
        append_str( p, hdr->name.s, to_tag.s-hdr->name.s);
2672
        /* to tag replacement */
2673
0
        bmark->to_tag_val.s=p;
2674
0
        bmark->to_tag_val.len=new_tag->len;
2675
0
        append_str( p, new_tag->s,new_tag->len);
2676
        /* the rest after to-tag */
2677
0
        append_str( p, to_tag.s+to_tag.len,
2678
0
          hdr->name.s+hdr->len-(to_tag.s+to_tag.len));
2679
0
      }else{ /* adding a new to-tag */
2680
0
        after_body=hdr->body.s+hdr->body.len;
2681
0
        append_str( p, hdr->name.s, after_body-hdr->name.s);
2682
0
        append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN);
2683
0
        bmark->to_tag_val.s=p;
2684
0
        bmark->to_tag_val.len=new_tag->len;
2685
0
        append_str( p, new_tag->s,new_tag->len);
2686
0
        append_str( p, after_body,
2687
0
                hdr->name.s+hdr->len-after_body);
2688
0
      }
2689
0
    } else {
2690
      /* no new to-tag -- proceed to 1:1 copying  */
2691
0
      totags=((struct to_body*)(hdr->parsed))->tag_value.s;
2692
0
      if (totags) {
2693
0
        bmark->to_tag_val.s=p+(totags-hdr->name.s);
2694
0
        bmark->to_tag_val.len=
2695
0
          ((struct to_body*)(hdr->parsed))->tag_value.len;
2696
0
      } else {
2697
0
        bmark->to_tag_val.s = NULL;
2698
0
        bmark->to_tag_val.len = 0;
2699
0
      }
2700
0
      append_str(p, hdr->name.s, hdr->len);
2701
0
    }
2702
0
  }
2703
  /* FROM header */
2704
0
  if (msg->from)
2705
0
    append_str(p, msg->from->name.s, msg->from->len);
2706
  /* CALLID header */
2707
0
  if (msg->callid)
2708
0
    append_str(p, msg->callid->name.s, msg->callid->len);
2709
  /* copy the CSEQ hdr */
2710
0
  if (msg->cseq)
2711
0
    append_str(p, msg->cseq->name.s, msg->cseq->len);
2712
  /* lumps */
2713
0
  for(lump=msg->reply_lump;lump;lump=lump->next)
2714
0
    if (lump->flags&LUMP_RPL_HDR){
2715
0
      memcpy(p,lump->text.s,lump->text.len);
2716
0
      p += lump->text.len;
2717
0
    }
2718
  /* server header */
2719
0
  if (server_signature) {
2720
0
    append_str( p, server_header->s, server_header->len);
2721
0
    append_str( p, CRLF, CRLF_LEN );
2722
0
  }
2723
  /* content_length hdr */
2724
0
  if (content_len_len) {
2725
0
    append_str( p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
2726
0
    append_str( p, content_len_buf, content_len_len );
2727
0
    append_str( p, CRLF, CRLF_LEN );
2728
0
  } else {
2729
0
    append_str( p, CONTENT_LENGTH"0"CRLF,CONTENT_LENGTH_LEN+1+CRLF_LEN);
2730
0
  }
2731
  /* warning header */
2732
0
  if (warning_buf) {
2733
0
    append_str( p, warning_buf, warning_len );
2734
0
    append_str( p, CRLF, CRLF_LEN );
2735
0
  }
2736
  /*end of message*/
2737
0
  memcpy( p, CRLF, CRLF_LEN );
2738
0
  p+=CRLF_LEN;
2739
  /* body */
2740
0
  if (body) {
2741
0
    append_str( p, body->text.s, body->text.len );
2742
0
  }
2743
2744
0
  if (len!=(unsigned long)(p-buf))
2745
0
    LM_CRIT("diff len=%d p-buf=%d\n", len, (int)(p-buf));
2746
2747
0
  *(p) = 0;
2748
0
  *returned_len = len;
2749
  /* in req2reply, received_buf is not introduced to lumps and
2750
     needs to be deleted here
2751
  */
2752
0
  if (received_buf) pkg_free(received_buf);
2753
0
  if (rport_buf) pkg_free(rport_buf);
2754
0
  return buf;
2755
2756
0
error01:
2757
0
  if (received_buf) pkg_free(received_buf);
2758
0
  if (rport_buf) pkg_free(rport_buf);
2759
0
error00:
2760
0
  *returned_len=0;
2761
0
  return 0;
2762
0
}
2763
2764
2765
2766
/*! \brief return number of chars printed or 0 if space exceeded;
2767
   assumes buffer size of at least MAX_BRANCH_PARAM_LEN
2768
 */
2769
int branch_builder( unsigned int hash_index,
2770
  /* only either parameter useful */
2771
  unsigned int label, char * char_v,
2772
  int branch,
2773
  char *branch_str, int *len )
2774
0
{
2775
2776
0
  char *begin;
2777
0
  int size;
2778
2779
  /* hash id provided ... start with it */
2780
0
  size=MAX_BRANCH_PARAM_LEN;
2781
0
  begin=branch_str;
2782
0
  *len=0;
2783
2784
0
  memcpy(begin, MCOOKIE, MCOOKIE_LEN );
2785
0
  size-=MCOOKIE_LEN;begin+=MCOOKIE_LEN;
2786
2787
0
  if (int2reverse_hex( &begin, &size, hash_index)==-1)
2788
0
    return 0;
2789
2790
0
  if (size) {
2791
0
    *begin=BRANCH_SEPARATOR;
2792
0
    begin++; size--;
2793
0
  } else return 0;
2794
2795
  /* string with request's characteristic value ... use it ... */
2796
0
  if (char_v) {
2797
0
    if (memcpy(begin,char_v,MD5_LEN)) {
2798
0
      begin+=MD5_LEN; size-=MD5_LEN;
2799
0
    } else return 0;
2800
0
  } else { /* ... use the "label" value otherwise */
2801
0
    if (int2reverse_hex( &begin, &size, label )==-1)
2802
0
      return 0;
2803
0
  }
2804
2805
0
  if (size) {
2806
0
    *begin=BRANCH_SEPARATOR;
2807
0
    begin++; size--;
2808
0
  } else return 0;
2809
2810
0
  if (int2reverse_hex( &begin, &size, branch)==-1)
2811
0
    return 0;
2812
2813
0
  *len=MAX_BRANCH_PARAM_LEN-size;
2814
0
  return size;
2815
2816
0
}
2817
2818
2819
char* via_builder( unsigned int *len,
2820
  const struct socket_info* send_sock,
2821
  str* branch, str* extra_params, int proto, struct hostport* hp)
2822
11.7k
{
2823
11.7k
  unsigned int via_len, extra_len;
2824
11.7k
  char *line_buf;
2825
11.7k
  int max_len, local_via_len=MY_VIA_LEN;
2826
11.7k
  const str* address_str; /* address displayed in via */
2827
11.7k
  const str* port_str; /* port no displayed in via */
2828
2829
  /* use pre-set address in via or the outbound socket one */
2830
11.7k
  if (hp && hp->host && hp->host->len)
2831
0
    address_str=hp->host;
2832
11.7k
  else
2833
11.7k
    address_str=get_adv_host(send_sock);
2834
2835
11.7k
  if (hp && hp->port && hp->port->len)
2836
0
    port_str=hp->port;
2837
11.7k
  else
2838
11.7k
    port_str=get_adv_port(send_sock);
2839
2840
11.7k
  max_len=local_via_len+address_str->len /* space in MY_VIA */
2841
11.7k
    +2 /* just in case it is a v6 address ... [ ] */
2842
11.7k
    +1 /*':'*/+port_str->len
2843
11.7k
    +(branch?(MY_BRANCH_LEN+branch->len):0)
2844
11.7k
    +(extra_params?extra_params->len:0)
2845
11.7k
    +CRLF_LEN+1;
2846
11.7k
  line_buf=pkg_malloc( max_len );
2847
11.7k
  if (line_buf==0){
2848
0
    ser_error=E_OUT_OF_MEM;
2849
0
    LM_ERR("out of pkg memory\n");
2850
0
    return 0;
2851
0
  }
2852
2853
11.7k
  extra_len=0;
2854
2855
11.7k
  memcpy(line_buf, MY_VIA, local_via_len);
2856
11.7k
  if (proto==PROTO_UDP){
2857
    /* do nothing */
2858
11.7k
  }else if (proto==PROTO_TCP){
2859
0
    memcpy(line_buf+local_via_len-4, "TCP ", 4);
2860
0
  }else if (proto==PROTO_TLS){
2861
0
    memcpy(line_buf+local_via_len-4, "TLS ", 4);
2862
0
  }else if(proto==PROTO_SCTP){
2863
0
    memcpy(line_buf+local_via_len-4, "SCTP ", 5);
2864
0
    local_via_len++;
2865
0
  }else if(proto==PROTO_WS){
2866
0
    memcpy(line_buf+local_via_len-4, "WS ", 3);
2867
0
    local_via_len--;
2868
0
  }else if(proto==PROTO_WSS){
2869
0
    memcpy(line_buf+local_via_len-4, "WSS ", 4);
2870
0
  }else{
2871
0
    LM_CRIT("unknown proto %d\n", proto);
2872
0
    return 0;
2873
0
  }
2874
2875
11.7k
  via_len=local_via_len+address_str->len; /*space included in MY_VIA*/
2876
2877
11.7k
  memcpy(line_buf+local_via_len+extra_len, address_str->s, address_str->len);
2878
11.7k
  line_buf[via_len]=':'; via_len++;
2879
11.7k
  memcpy(line_buf+via_len, port_str->s, port_str->len);
2880
11.7k
  via_len+=port_str->len;
2881
2882
  /* branch parameter */
2883
11.7k
  if (branch){
2884
11.7k
    memcpy(line_buf+via_len, MY_BRANCH, MY_BRANCH_LEN );
2885
11.7k
    via_len+=MY_BRANCH_LEN;
2886
11.7k
    memcpy(line_buf+via_len, branch->s, branch->len );
2887
11.7k
    via_len+=branch->len;
2888
11.7k
  }
2889
  /* extra params  */
2890
11.7k
  if (extra_params){
2891
5.49k
    memcpy(line_buf+via_len, extra_params->s, extra_params->len);
2892
5.49k
    via_len+=extra_params->len;
2893
5.49k
  }
2894
2895
11.7k
  memcpy(line_buf+via_len, CRLF, CRLF_LEN);
2896
11.7k
  via_len+=CRLF_LEN;
2897
11.7k
  line_buf[via_len]=0; /* null terminate the string*/
2898
2899
11.7k
  *len = via_len;
2900
11.7k
  return line_buf;
2901
11.7k
}
2902
2903
#define MAX_URI_LEN   1024
2904
static char uri_buff[MAX_URI_LEN];
2905
char *construct_uri(str *protocol,str *username,str *domain,str *port,
2906
    str *params,int *len)
2907
0
{
2908
0
  int pos = 0;
2909
2910
0
  if (!len)
2911
0
  {
2912
0
    LM_ERR("null pointer provided for construct_uri \n");
2913
0
    return 0;
2914
0
  }
2915
2916
0
  if (!protocol->s || protocol->len == 0)
2917
0
  {
2918
0
    LM_ERR("no protocol specified\n");
2919
0
    return 0;
2920
0
  }
2921
2922
0
  if (!domain->s || domain->len == 0)
2923
0
  {
2924
0
    LM_ERR("no domain specified\n");
2925
0
    return 0;
2926
0
  }
2927
2928
0
  memcpy(uri_buff,protocol->s,protocol->len);
2929
0
  pos += protocol->len;
2930
0
  uri_buff[pos++] = ':';
2931
2932
0
  if (username && username->s && username->len != 0)
2933
0
  {
2934
0
    memcpy(uri_buff+pos,username->s,username->len);
2935
0
    pos += username->len;
2936
0
    uri_buff[pos++] = '@';
2937
0
  }
2938
2939
0
  memcpy(uri_buff+pos,domain->s,domain->len);
2940
0
  pos += domain->len;
2941
2942
0
  if (port && port->s && port->len !=0)
2943
0
  {
2944
0
    uri_buff[pos++] = ':';
2945
0
    memcpy(uri_buff+pos,port->s,port->len);
2946
0
    pos += port->len;
2947
0
  }
2948
2949
0
  if (params && params->s && params->len !=0 )
2950
0
  {
2951
0
    uri_buff[pos++] = ';';
2952
0
    memcpy(uri_buff+pos,params->s,params->len);
2953
0
    pos += params->len;
2954
0
  }
2955
2956
0
  uri_buff[pos] = 0;
2957
0
  *len = pos;
2958
0
  return uri_buff;
2959
0
}
2960
2961
/* uses uri_buff above, since contact is still an uri */
2962
char *contact_builder(const struct socket_info* send_sock, int *ct_len)
2963
0
{
2964
0
  char *p;
2965
0
  int proto_len = 0;
2966
0
  const str* address_str = get_adv_host(send_sock);
2967
0
  const str* port_str = get_adv_port(send_sock);
2968
2969
  /* sip: */
2970
0
  p = uri_buff;
2971
0
  memcpy(p, "sip:", 4);
2972
0
  p += 4;
2973
2974
  /* host */
2975
0
  memcpy(p, address_str->s, address_str->len);
2976
0
  p += address_str->len;
2977
2978
  /* :port */
2979
0
  *p++ = ':';
2980
0
  memcpy(p, port_str->s, port_str->len);
2981
0
  p += port_str->len;
2982
2983
  /* transport if needed */
2984
0
  if (send_sock->proto != PROTO_UDP) {
2985
0
    memcpy(p, ";transport=", 11);
2986
0
    p += 11;
2987
0
    proto_len = strlen(protos[send_sock->proto].name);
2988
0
    memcpy(p, protos[send_sock->proto].name, proto_len);
2989
0
    p += proto_len;
2990
0
  }
2991
2992
0
  *p = '\0';
2993
2994
0
  if (ct_len)
2995
0
    *ct_len = p - uri_buff;
2996
2997
0
  return uri_buff;
2998
0
}