Coverage Report

Created: 2025-07-11 06:28

/src/opensips/msg_translator.c
Line
Count
Source (jump to first uncovered line)
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
0
{
145
0
  int rcvd;
146
147
0
  if(msg->via1->received !=NULL)
148
0
    return 1;
149
150
0
  if(msg->via1->maddr){
151
0
    rcvd = check_ip_address(&msg->rcv.src_ip, &msg->via1->maddr->value,
152
0
      msg->via1->port, msg->via1->proto, received_dns);
153
0
  } else {
154
0
    rcvd = check_ip_address(&msg->rcv.src_ip,
155
0
      &msg->via1->host, msg->via1->port, msg->via1->proto, received_dns);
156
0
  }
157
158
0
  return rcvd;
159
0
}
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
0
{
241
0
  char *buf, *tmp;
242
0
  int  len, tmp_len;
243
0
  struct ip_addr *source_ip;
244
245
0
  source_ip=&msg->rcv.src_ip;
246
247
0
  buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
248
0
  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
0
  memcpy(buf, RECEIVED, RECEIVED_LEN);
254
0
  if ( (tmp=ip_addr2a(source_ip))==0)
255
0
    return 0; /* error*/
256
0
  tmp_len=strlen(tmp);
257
0
  len=RECEIVED_LEN+tmp_len;
258
259
0
  memcpy(buf+RECEIVED_LEN, tmp, tmp_len);
260
0
  buf[len]=0; /*null terminate it */
261
262
0
  *received_len = len;
263
0
  return buf;
264
0
}
265
266
267
268
char* rport_builder(struct sip_msg *msg, unsigned int *rport_len)
269
0
{
270
0
  char* buf, * tmp;
271
0
  int len, tmp_len;
272
273
0
  tmp_len=0;
274
0
  tmp=int2str(msg->rcv.src_port, &tmp_len);
275
0
  len=RPORT_LEN+tmp_len;
276
0
  buf=pkg_malloc(sizeof(char)*(len+1));/* space for null term */
277
0
  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
0
  memcpy(buf, RPORT, RPORT_LEN);
283
0
  memcpy(buf+RPORT_LEN, tmp, tmp_len);
284
0
  buf[len]=0; /*null terminate it*/
285
286
0
  *rport_len=len;
287
0
  return buf;
288
0
}
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
0
{
452
0
  unsigned int s_offset, new_len;
453
0
  unsigned int last_del;
454
0
  struct lump *t, *r;
455
0
  const str *send_address_str, *send_port_str;
456
0
  const str *rcv_address_str=NULL;
457
0
  const str *rcv_port_str=NULL;
458
459
0
#define SUBST_LUMP_LEN(subst_l) \
460
0
    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
0
  s_offset=0;
602
0
  new_len=0;
603
0
  last_del=0;
604
605
  /* init send_address_str & send_port_str */
606
0
  if(send_sock && send_sock->adv_name_str.len)
607
0
    send_address_str=&(send_sock->adv_name_str);
608
0
  else if (msg->set_global_address.s)
609
0
    send_address_str=&(msg->set_global_address);
610
0
  else if (default_global_address->s)
611
0
    send_address_str=default_global_address;
612
0
  else
613
0
    send_address_str=&(send_sock->address_str);
614
615
0
  if(send_sock && send_sock->adv_port_str.len)
616
0
    send_port_str=&(send_sock->adv_port_str);
617
0
  else if (msg->set_global_port.s)
618
0
    send_port_str=&(msg->set_global_port);
619
0
  else if (default_global_port->s)
620
0
    send_port_str=default_global_port;
621
0
  else
622
0
    send_port_str=&(send_sock->port_no_str);
623
624
  /* init rcv_address_str & rcv_port_str */
625
0
  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
0
  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
0
    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
0
    for (r = t->before; r; r = r->before) {
649
0
      switch (r->op) {
650
0
        case LUMP_ADD:
651
0
          new_len += r->len;
652
0
          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
0
      }
673
0
    }
674
0
skip_before:
675
0
    switch (t->op) {
676
0
      case LUMP_DEL:
677
0
        last_del=t->u.offset;
678
679
0
        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
0
        } else {
685
0
          new_len -= t->len;
686
0
          s_offset = t->u.offset + t->len;
687
0
        }
688
689
0
        break;
690
0
      case LUMP_NOP:
691
        /* do nothing */
692
0
        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
0
    }
714
715
0
    for (r = t->after; r; r = r->after) {
716
0
      switch (r->op) {
717
0
        case LUMP_ADD:
718
0
          new_len+=r->len;
719
0
          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
0
      }
740
0
    }
741
0
skip_after:
742
0
    ; /* to make gcc 3.* happy */
743
0
  }
744
0
  return new_len;
745
0
}
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
0
{
760
0
  struct lump *t, *r;
761
0
  char* orig;
762
0
  unsigned int size, offset, s_offset;
763
0
  unsigned int last_del;
764
0
  const str *send_address_str, *send_port_str;
765
0
  const str *rcv_address_str=NULL;
766
0
  const str *rcv_port_str=NULL;
767
768
0
#define SUBST_LUMP(subst_l) \
769
0
  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
0
 \
1014
0
1015
  /* init send_address_str & send_port_str */
1016
0
  if(send_sock && send_sock->adv_name_str.len)
1017
0
    send_address_str=&(send_sock->adv_name_str);
1018
0
  else if (msg->set_global_address.len)
1019
0
    send_address_str=&(msg->set_global_address);
1020
0
  else if (default_global_address->s)
1021
0
    send_address_str=default_global_address;
1022
0
  else
1023
0
    send_address_str=&(send_sock->address_str);
1024
0
  if(send_sock && send_sock->adv_port_str.len)
1025
0
    send_port_str=&(send_sock->adv_port_str);
1026
0
  else if (msg->set_global_port.len)
1027
0
    send_port_str=&(msg->set_global_port);
1028
0
  else if (default_global_port->s)
1029
0
    send_port_str=default_global_port;
1030
0
  else
1031
0
    send_port_str=&(send_sock->port_no_str);
1032
1033
  /* init rcv_address_str & rcv_port_str */
1034
0
  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
0
  orig=msg->buf;
1050
0
  offset=*new_buf_offs;
1051
0
  s_offset=*orig_offs;
1052
0
  last_del=0;
1053
1054
0
  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
0
    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
0
    switch (t->op) {
1063
0
      case LUMP_NOP:
1064
0
      case LUMP_DEL:
1065
        /* copy till offset (if any) */
1066
0
        if (s_offset < t->u.offset) {
1067
0
          size = t->u.offset-s_offset;
1068
0
          memcpy(new_buf+offset, orig+s_offset, size);
1069
0
          offset += size;
1070
0
          s_offset += size;
1071
0
        }
1072
1073
0
        if (t->op == LUMP_DEL)
1074
0
          last_del = t->u.offset;
1075
1076
        /* process before  */
1077
0
        for (r = t->before; r; r = r->before) {
1078
0
          switch (r->op) {
1079
0
            case LUMP_ADD:
1080
              /*just add it here*/
1081
0
              memcpy(new_buf+offset, r->u.value, r->len);
1082
0
              offset += r->len;
1083
0
              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
0
          }
1104
0
        }
1105
0
skip_nop_before:
1106
0
        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
0
          if (t->u.offset + t->len > s_offset)
1112
0
            s_offset += t->len - (s_offset - t->u.offset);
1113
0
        }
1114
1115
        /* process after */
1116
0
        for (r = t->after; r; r = r->after) {
1117
0
          switch (r->op) {
1118
0
            case LUMP_ADD:
1119
              /*just add it here*/
1120
0
              memcpy(new_buf+offset, r->u.value, r->len);
1121
0
              offset += r->len;
1122
0
              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
0
          }
1143
0
        }
1144
0
skip_nop_after:
1145
0
        break;
1146
0
      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
0
    }
1240
0
  }
1241
1242
0
  *new_buf_offs = offset;
1243
0
  *orig_offs = s_offset;
1244
0
}
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
0
{
1258
0
  struct body_part *part;
1259
0
  struct lump* lump;
1260
0
  struct lump* ct;
1261
0
  unsigned int size;
1262
0
  unsigned int len = 0;
1263
0
  unsigned int orig_offs;
1264
0
  struct hdr_field hf;
1265
0
  char *hdr, *it;
1266
1267
  /* set the offset (in the original buffer) at the beginning of the body */
1268
0
  orig_offs = (msg->body && msg->body->body.s) ?
1269
0
    msg->body->body.s-msg->buf : msg->len ;
1270
1271
0
  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
0
  } 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
0
    LM_DBG("only one part to be added\n");
1290
1291
0
    for( part=&msg->body->first ; part ; part=part->next)
1292
0
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED)==0 ) break;
1293
1294
0
    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
0
    LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1300
0
      part->flags, part->mime_s.len, part->mime_s.s, part->dump_f);
1301
1302
0
    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
0
    } else {
1313
0
      if ( part->flags & SIP_BODY_PART_FLAG_NEW ) {
1314
        /* simpy copy the body of the part */
1315
0
        len += part->body.len;
1316
0
      } else {
1317
        /* this is one part that was received (so potentially
1318
         * modified during runtime) -> apply all body lumps
1319
         * inside this part */
1320
0
        orig_offs = part->body.s - msg->buf;
1321
0
        lump = msg->body_lumps;
1322
0
        while ( lump && lump->u.offset < orig_offs )
1323
0
          lump=lump->next;
1324
0
        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
0
        len += (part->body.s+part->body.len-msg->buf)-orig_offs;
1331
0
      }
1332
0
    }
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
0
    if ( (part->flags & SIP_BODY_PART_FLAG_NEW)
1338
0
    || 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
0
      if ( (part->flags & SIP_BODY_PART_FLAG_NEW)==0 &&
1400
0
      msg->body->part_count==1 &&
1401
0
      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
0
  } 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
0
  LM_DBG("resulting body len is %d\n",len);
1585
0
  return len;
1586
0
}
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
0
{
1593
0
  struct body_part *part;
1594
0
  struct lump* lump;
1595
0
  unsigned int size;
1596
0
  unsigned int offset;
1597
0
  int padding=0;
1598
1599
0
  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
0
  } 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
0
    LM_DBG("only one part to be added\n");
1610
1611
0
    for( part=&msg->body->first ; part ; part=part->next)
1612
0
      if ( (part->flags & SIP_BODY_PART_FLAG_DELETED)==0 ) break;
1613
1614
0
    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
0
    LM_DBG("handing part with flags %x, mime %.*s, dump function %p\n",
1620
0
      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
0
    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
0
    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
0
    } else {
1647
0
      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
0
      } else {
1652
        /* this is one part that was received (so potentially
1653
         * modified during runtime) -> apply all body lumps
1654
         * inside this part */
1655
0
        *orig_offs = part->body.s - msg->buf;
1656
0
        lump = msg->body_lumps;
1657
0
        while ( lump && lump->u.offset<(part->body.s-msg->buf) )
1658
0
          lump=lump->next;
1659
0
        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
0
        size = (part->body.s+part->body.len-msg->buf)-*orig_offs;
1667
0
        memcpy(new_buf+*new_offs, msg->buf+*orig_offs, size);
1668
0
        *new_offs += size;
1669
0
      }
1670
0
    }
1671
1672
0
    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
0
  } 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
0
  return;
1878
0
}
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
0
{
1889
0
  str body, rcv_body = STR_NULL;
1890
0
  struct sdp_body_part_ops *ops;
1891
1892
0
  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
0
  if (msg->body==NULL) {
1905
    /* no body parsed, no advanced ops done, just dummy lumps over body */
1906
0
    return lumps_len(msg, msg->body_lumps, sock, -1);
1907
0
  } else {
1908
0
    return ((int)prep_reassemble_body_parts( msg, sock) - msg->body->body.len);
1909
0
  }
1910
0
}
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
0
{
1923
0
  unsigned int size;
1924
0
  str body;
1925
1926
  /* apply changes over the SIP headers */
1927
0
  process_lumps(msg, msg->add_rm, new_buf, new_offs, orig_offs, sock, -1);
1928
1929
  /* real-time SDP changes */
1930
0
  if (have_sdp_ops(msg)) {
1931
0
    if (get_body(msg, &body) != 0 || body.len==0)
1932
0
      return;
1933
1934
0
    memcpy(new_buf+*new_offs, msg->sdp_ops->sep, msg->sdp_ops->sep_len);
1935
0
    *new_offs += msg->sdp_ops->sep_len;
1936
1937
0
    memcpy(new_buf+*new_offs, body.s, body.len);
1938
0
    *new_offs += body.len;
1939
0
    return;
1940
0
  }
1941
1942
  /* lumps-based SDP changes */
1943
0
  if (msg->body==NULL) {
1944
    /* no body parsed, no advanced ops done, just dummy lumps over body */
1945
0
    process_lumps(msg, msg->body_lumps, new_buf, new_offs,
1946
0
      orig_offs, sock, max_offset);
1947
    /* copy the rest of the message */
1948
0
    memcpy(new_buf+*new_offs, msg->buf+*orig_offs, max_offset-*orig_offs);
1949
0
    *new_offs += max_offset-*orig_offs;
1950
0
  } else {
1951
    /* copy whatever is left in the original buffer (up to the body) */
1952
0
    size = msg->body->body.s ?
1953
0
      ((msg->body->body.s - msg->buf) - *orig_offs)  /* msg had body */
1954
0
      : (msg->len - *orig_offs);                     /* no body at all */
1955
0
    memcpy(new_buf+*new_offs, msg->buf+*orig_offs, size );
1956
0
    *new_offs += size;
1957
0
    *orig_offs += size;
1958
    /* rebuild the body, part by part, in a content wise manner */
1959
0
    reassemble_body_parts(msg, new_buf, new_offs, orig_offs, sock);
1960
0
  }
1961
0
}
1962
1963
1964
/*! \brief
1965
 * Adjust/insert Content-Length if necessary
1966
 */
1967
static inline int adjust_clen(struct sip_msg* msg, int body_delta, int proto)
1968
0
{
1969
0
  struct lump* anchor;
1970
0
  char* clen_buf;
1971
0
  int clen_len;
1972
1973
  /* Calculate message length difference caused by lumps modifying message
1974
   * body, from this point on the message body must not be modified. Zero
1975
   * value indicates that the body hasn't been modified
1976
  */
1977
1978
0
  clen_buf = 0;
1979
0
  anchor=0;
1980
1981
  /* check to see if we need to add clen */
1982
0
  if (is_tcp_based_proto(proto)) {
1983
0
    if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1){
1984
0
      LM_ERR("parsing content-length\n");
1985
0
      goto error;
1986
0
    }
1987
0
    if (msg->content_length==0){
1988
      /* not present, we need to add it */
1989
      /* msg->unparsed should point just before the final crlf
1990
       * - whole message was parsed by the above parse_headers
1991
       *   which did not find content-length */
1992
0
      anchor=anchor_lump(msg, msg->unparsed-msg->buf,
1993
0
                        HDR_CONTENTLENGTH_T);
1994
0
      if (anchor==0){
1995
0
        LM_ERR("cannot set clen anchor\n");
1996
0
        goto error;
1997
0
      }
1998
0
    }
1999
0
  }
2000
2001
0
  if ((anchor==0) && body_delta){
2002
0
    if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) {
2003
0
      LM_ERR("parsing Content-Length\n");
2004
0
      goto error;
2005
0
    }
2006
2007
    /* The body has been changed, try to find
2008
     * existing Content-Length
2009
     */
2010
    /* no need for Content-Length if it's and UDP packet and
2011
     * it hasn't Content-Length already */
2012
0
    if (msg->content_length==0){
2013
        /* content-length doesn't exist, append it */
2014
      /* msg->unparsed should point just before the final crlf
2015
       * - whole message was parsed by the above parse_headers
2016
       *   which did not find content-length */
2017
0
      if (proto!=PROTO_UDP){
2018
0
        anchor=anchor_lump(msg, msg->unparsed-msg->buf,
2019
0
                          HDR_CONTENTLENGTH_T);
2020
0
        if (anchor==0){
2021
0
          LM_ERR("cannot set clen anchor\n");
2022
0
          goto error;
2023
0
        }
2024
0
      }else{
2025
0
        LM_DBG("the UDP packet has no clen => not adding one \n");
2026
0
      }
2027
0
    }else{
2028
      /* Content-Length has been found, remove it */
2029
0
      anchor = del_lump(  msg, msg->content_length->name.s - msg->buf,
2030
0
                msg->content_length->len, HDR_CONTENTLENGTH_T);
2031
0
      if (anchor==0) {
2032
0
        LM_ERR("can't remove original Content-Length\n");
2033
0
        goto error;
2034
0
      }
2035
0
    }
2036
0
  }
2037
2038
0
  if (anchor){
2039
0
    clen_buf = clen_builder(msg, &clen_len, body_delta);
2040
0
    if (!clen_buf) goto error;
2041
0
    if (insert_new_lump_after(anchor, clen_buf, clen_len,
2042
0
          HDR_CONTENTLENGTH_T) == 0)
2043
0
      goto error;
2044
0
  }
2045
2046
0
  return 0;
2047
0
error:
2048
0
  if (clen_buf) pkg_free(clen_buf);
2049
0
  return -1;
2050
0
}
2051
2052
2053
/*! \brief
2054
 * Save given Path body as Route header in message.
2055
 *
2056
 * If another Route HF is found, it's placed right before that.
2057
 * Otherwise, it's placed after the last Via HF. If also no
2058
 * Via HF is found, it's placed as first HF.
2059
 */
2060
0
#define ROUTE_STR  "Route: "
2061
0
#define ROUTE_LEN  (sizeof(ROUTE_STR)-1)
2062
static inline int insert_path_as_route(struct sip_msg* msg, str* path)
2063
0
{
2064
0
  struct lump *anchor;
2065
0
  char *route;
2066
0
  struct hdr_field *hf, *last_via=0;
2067
2068
0
  for (hf = msg->headers; hf; hf = hf->next) {
2069
0
    if (hf->type == HDR_ROUTE_T) {
2070
0
      break;
2071
0
    } else if (hf->type == HDR_VIA_T) {
2072
0
      last_via = hf;
2073
0
    }
2074
0
  }
2075
0
  if (hf) {
2076
    /* Route HF found, insert before it */
2077
0
    anchor = anchor_lump(msg, hf->name.s - msg->buf, 0);
2078
0
  } else if(last_via) {
2079
0
    if (last_via->next) {
2080
      /* Via HF in between, insert after it */
2081
0
      anchor = anchor_lump(msg, last_via->next->name.s - msg->buf, 0);
2082
0
    } else {
2083
      /* Via HF is last, so append */
2084
0
      anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0);
2085
0
    }
2086
0
  } else {
2087
    /* None of the above, insert as first */
2088
0
    anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0);
2089
0
  }
2090
2091
0
  if (anchor == 0) {
2092
0
    LM_ERR("failed to get anchor\n");
2093
0
    return -1;
2094
0
  }
2095
2096
0
  route = pkg_malloc(ROUTE_LEN + path->len + CRLF_LEN);
2097
0
  if (!route) {
2098
0
    LM_ERR("out of pkg memory\n");
2099
0
    return -1;
2100
0
  }
2101
0
  memcpy(route, ROUTE_STR, ROUTE_LEN);
2102
0
  memcpy(route + ROUTE_LEN, path->s, path->len);
2103
0
  memcpy(route + ROUTE_LEN + path->len, CRLF, CRLF_LEN);
2104
2105
0
  if (insert_new_lump_before(anchor, route, ROUTE_LEN + path->len + CRLF_LEN, 0) == 0) {
2106
0
    LM_ERR("failed to insert lump\n");
2107
0
    return -1;
2108
0
  }
2109
2110
0
  msg->msg_flags |= FL_HAS_ROUTE_LUMP;
2111
2112
0
  return 0;
2113
0
}
2114
2115
int is_del_via1_lump(struct sip_msg* msg)
2116
0
{
2117
0
  struct lump* lump;
2118
0
  int via1_off, via1_len;
2119
2120
/*  for(lump= msg->add_rm; lump; lump= lump->next)
2121
    if(lump->type == HDR_VIA1_T && lump->op== LUMP_DEL)
2122
      return 1;
2123
*/
2124
0
  if(!msg->h_via1)
2125
0
    return 0;
2126
2127
0
  via1_off = msg->h_via1->name.s - msg->buf;
2128
0
  via1_len = msg->h_via1->len;
2129
2130
0
  for(lump= msg->add_rm; lump; lump= lump->next)
2131
0
  {
2132
0
    if(lump->type == 0 && lump->op== LUMP_DEL && lump->u.offset == via1_off && lump->len == via1_len)
2133
0
      return 1;
2134
0
  }
2135
0
  return 0;
2136
0
}
2137
2138
char * build_req_buf_from_sip_req( struct sip_msg* msg,
2139
                unsigned int *returned_len,
2140
                const struct socket_info* send_sock, int proto,
2141
                str *via_params, unsigned int flags)
2142
0
{
2143
0
  unsigned int len, new_len, received_len, rport_len, uri_len, via_len, body_delta;
2144
0
  char *line_buf, *received_buf, *rport_buf, *new_buf, *buf, *id_buf;
2145
0
  unsigned int offset, s_offset, size, id_len;
2146
0
  struct lump *anchor, *via_insert_param;
2147
0
  str branch, extra_params, body;
2148
0
  struct hostport hp;
2149
2150
0
  id_buf=0;
2151
0
  id_len=0;
2152
0
  via_insert_param=0;
2153
0
  extra_params.len=0;
2154
0
  extra_params.s=0;
2155
0
  uri_len=0;
2156
0
  buf=msg->buf;
2157
0
  len=msg->len;
2158
0
  received_len=0;
2159
0
  rport_len=0;
2160
0
  new_buf=0;
2161
0
  received_buf=0;
2162
0
  rport_buf=0;
2163
0
  line_buf=0;
2164
0
  int via1_deleted = 0;
2165
2166
0
  if (msg->path_vec.len) {
2167
0
    if (insert_path_as_route(msg, &msg->path_vec) < 0) {
2168
0
      LM_ERR("adding path lumps failed\n");
2169
0
      goto error;
2170
0
    }
2171
0
  }
2172
2173
  /* Calculate message body difference and adjust
2174
   * Content-Length
2175
   */
2176
0
  body_delta = calculate_body_diff( msg, send_sock);
2177
0
  if (adjust_clen(msg, body_delta, proto) < 0) {
2178
0
    LM_ERR("failed to adjust Content-Length\n");
2179
0
    goto error;
2180
0
  }
2181
2182
0
  if (flags&MSG_TRANS_NOVIA_FLAG)
2183
0
    goto build_msg;
2184
2185
  /* add id if tcp-based protocol  */
2186
0
  if (is_tcp_based_proto(msg->rcv.proto)) {
2187
0
    if  ((id_buf=id_builder(msg, &id_len))==0){
2188
0
      LM_ERR("id_builder failed\n");
2189
0
      goto error; /* we don't need to free anything,
2190
                       nothing alloc'ed yet*/
2191
0
    }
2192
0
    LM_DBG("id added: <%.*s>, rcv proto=%d\n",
2193
0
        (int)id_len, id_buf, msg->rcv.proto);
2194
    /* if there was already something there, simply copy them */
2195
0
    if (via_params && via_params->len != 0) {
2196
0
      extra_params.len = id_len + via_params->len;
2197
0
      extra_params.s=pkg_malloc(extra_params.len);
2198
0
      if(extra_params.s==0) {
2199
0
        LM_ERR("extra params building failed\n");
2200
0
        pkg_free(id_buf);
2201
0
        goto error;
2202
0
      }
2203
0
      memcpy(extra_params.s, via_params->s, via_params->len);
2204
0
      memcpy(extra_params.s + via_params->len, id_buf, id_len);
2205
0
      pkg_free(id_buf);
2206
0
    } else {
2207
0
      extra_params.s=id_buf;
2208
0
      extra_params.len=id_len;
2209
0
    }
2210
0
  }
2211
2212
  /* check whether to add rport parameter to local via */
2213
0
  if(msg->msg_flags&FL_FORCE_LOCAL_RPORT) {
2214
0
    id_buf=extra_params.s;
2215
0
    id_len=extra_params.len;
2216
0
    if (via_params && !extra_params.len) {
2217
      /* if no other parameters were added yet, consider via_params */
2218
0
      extra_params.len = via_params->len;
2219
      /* otherwise, the via_params were already copied in the id block */
2220
0
    }
2221
0
    extra_params.len += RPORT_LEN-1; /* last char in RPORT define is '='
2222
                    which is not added, but the new buffer
2223
                    will be null terminated */
2224
0
    extra_params.s = (char*)pkg_malloc(extra_params.len+1);
2225
0
    if(extra_params.s==0) {
2226
0
      LM_ERR("extra params building failed\n");
2227
0
      if (id_buf) pkg_free(id_buf);
2228
0
      goto error;
2229
0
    }
2230
2231
0
    if(id_buf!=0) {
2232
0
      memcpy(extra_params.s, id_buf, id_len);
2233
0
      pkg_free(id_buf);
2234
0
    } else if (via_params) {
2235
0
      memcpy(extra_params.s, via_params->s, via_params->len);
2236
0
      id_len = via_params->len;
2237
0
    }
2238
0
    memcpy(extra_params.s+id_len, RPORT, RPORT_LEN-1);
2239
0
    extra_params.s[extra_params.len]='\0';
2240
0
    LM_DBG("extra param added: <%.*s>\n",extra_params.len, extra_params.s);
2241
0
  }
2242
2243
0
  branch.s=msg->add_to_branch_s;
2244
0
  branch.len=msg->add_to_branch_len;
2245
0
  set_hostport(&hp, msg);
2246
0
  line_buf = via_builder( &via_len, send_sock, &branch,
2247
0
            extra_params.len?&extra_params:via_params, proto, &hp);
2248
0
  if (!line_buf){
2249
0
    LM_ERR("no via received!\n");
2250
0
    goto error00;
2251
0
  }
2252
2253
0
  via1_deleted = is_del_via1_lump(msg);
2254
  /* check if received needs to be added:
2255
   *  - if the VIA address and the received address are different
2256
   *  - if the rport was forced (rport requires received)
2257
   *  - if the rport was received in the VIA hdr
2258
   *  - and there is no lump that delets VIA1 hdr */
2259
0
  if ( (msg->via1->rport || (msg->msg_flags&FL_FORCE_RPORT) ||
2260
0
      received_test(msg) ) && !via1_deleted) {
2261
0
    if ((received_buf=received_builder(msg,&received_len))==0){
2262
0
      LM_ERR("received_builder failed\n");
2263
0
      goto error01;  /* free also line_buf */
2264
0
    }
2265
0
  }
2266
2267
  /* check if rport needs to be updated:
2268
   *  - if FL_FORCE_RPORT is set add it (and del. any previous version)
2269
   *  - if via already contains an rport add it and overwrite the previous
2270
   *  rport value if present (if you don't want to overwrite the previous
2271
   *  version remove the comments) */
2272
0
  if (((msg->msg_flags&FL_FORCE_RPORT)||
2273
0
      (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)) && !via1_deleted){
2274
0
    if ((rport_buf=rport_builder(msg, &rport_len))==0){
2275
0
      LM_ERR("rport_builder failed\n");
2276
0
      goto error01; /* free everything */
2277
0
    }
2278
0
  }
2279
2280
  /* add via header to the list */
2281
  /* try to add it before msg. 1st via */
2282
  /* add first via, as an anchor for second via*/
2283
0
  anchor=anchor_lump(msg, msg->via1->hdr.s-buf, HDR_VIA_T);
2284
0
  if (anchor==0) goto error01;
2285
0
  if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA_T)==0)
2286
0
    goto error01;
2287
  /* find out where the offset of the first parameter that should be added
2288
   * (after host:port), needed by add receive & maybe rport */
2289
0
  if (msg->via1->params.s){
2290
0
      size= msg->via1->params.s-msg->via1->hdr.s-1; /*compensate
2291
                              for ';' */
2292
0
  }else{
2293
0
      size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
2294
0
      if (msg->via1->port!=0){
2295
        /*size+=strlen(msg->via1->hdr.s+size+1)+1;*/
2296
0
        size += msg->via1->port_str.len + 1; /* +1 for ':'*/
2297
0
      }
2298
0
  }
2299
  /* if received needs to be added, add anchor after host and add it, or
2300
   * overwrite the previous one if already present */
2301
0
  if (received_len){
2302
0
    if (msg->via1->received){ /* received already present => overwrite it*/
2303
0
      via_insert_param=del_lump(msg,
2304
0
                msg->via1->received->start-buf-1, /*;*/
2305
0
                msg->via1->received->size+1, /*;*/ HDR_VIA_T);
2306
0
    }else if (via_insert_param==0){ /* receive not present, ok */
2307
0
      via_insert_param=anchor_lump(msg,
2308
0
                    msg->via1->hdr.s-buf+size, HDR_VIA_T);
2309
0
    }
2310
0
    if (via_insert_param==0) goto error02; /* free received_buf */
2311
0
    if (insert_new_lump_after(via_insert_param, received_buf, received_len,
2312
0
          HDR_VIA_T) ==0 ) goto error02; /* free received_buf */
2313
0
  }
2314
  /* if rport needs to be updated, delete it if present and add it's value */
2315
0
  if (rport_len){
2316
0
    if (msg->via1->rport){ /* rport already present */
2317
0
      via_insert_param=del_lump(msg,
2318
0
                msg->via1->rport->start-buf-1, /*';'*/
2319
0
                msg->via1->rport->size+1 /* ; */, HDR_VIA_T);
2320
0
    }else if (via_insert_param==0){ /*force rport, no rport present */
2321
      /* no rport, add it */
2322
0
      via_insert_param=anchor_lump(msg,
2323
0
                  msg->via1->hdr.s-buf+size, HDR_VIA_T);
2324
0
    }
2325
0
    if (via_insert_param==0) goto error03; /* free rport_buf */
2326
0
    if (insert_new_lump_after(via_insert_param, rport_buf, rport_len,
2327
0
                  HDR_VIA_T) ==0 )
2328
0
      goto error03; /* free rport_buf */
2329
0
  }
2330
2331
0
build_msg:
2332
  /* adjust len to the useful part of the message */
2333
0
  if (!have_sdp_ops(msg) && get_body(msg, &body) == 0 && body.len)
2334
0
    len -= (msg->buf + msg->len - body.s - body.len);
2335
2336
  /* compute new msg len and fix overlapping zones*/
2337
0
  new_len=len+body_delta+lumps_len(msg, msg->add_rm, send_sock,-1);
2338
#ifdef XL_DEBUG
2339
  LM_DBG("new_len(%d)=len(%d)+lumps_len\n", new_len, len);
2340
#endif
2341
2342
0
  if (msg->new_uri.s){
2343
0
    uri_len=msg->new_uri.len;
2344
0
    new_len=new_len-msg->first_line.u.request.uri.len+uri_len;
2345
0
  }
2346
0
  if (flags&MSG_TRANS_SHM_FLAG)
2347
0
    new_buf=(char*)shm_malloc(new_len+1);
2348
0
  else
2349
0
    new_buf=(char*)pkg_malloc(new_len+1);
2350
0
  if (new_buf==0){
2351
0
    ser_error=E_OUT_OF_MEM;
2352
0
    LM_ERR("out of pkg memory\n");
2353
0
    goto error00;
2354
0
  }
2355
2356
0
  offset=s_offset=0;
2357
0
  if (msg->new_uri.s){
2358
    /* copy message up to uri */
2359
0
    size=msg->first_line.u.request.uri.s-buf;
2360
0
    memcpy(new_buf, buf, size);
2361
0
    offset+=size;
2362
0
    s_offset+=size;
2363
    /* add our uri */
2364
0
    memcpy(new_buf+offset, msg->new_uri.s, uri_len);
2365
0
    offset+=uri_len;
2366
0
    s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */
2367
0
  }
2368
2369
  /* apply changes over SIP hdrs and body */
2370
0
  apply_msg_changes( msg, new_buf, &offset, &s_offset, send_sock, len);
2371
0
  if (offset!=new_len) {
2372
0
    LM_BUG("len mismatch : calculated %d, written %d\n", new_len, offset);
2373
0
    abort();
2374
0
  }
2375
2376
0
  new_buf[new_len]=0;
2377
2378
0
  *returned_len=new_len;
2379
  /* cleanup */
2380
0
  if (extra_params.s) pkg_free(extra_params.s);
2381
0
  return new_buf;
2382
2383
0
error01:
2384
0
  if (line_buf) pkg_free(line_buf);
2385
0
error02:
2386
0
  if (received_buf) pkg_free(received_buf);
2387
0
error03:
2388
0
  if (rport_buf) pkg_free(rport_buf);
2389
0
error00:
2390
0
  if (extra_params.s) pkg_free(extra_params.s);
2391
0
error:
2392
0
  *returned_len=0;
2393
0
  return 0;
2394
0
}
2395
2396
2397
2398
char * build_res_buf_from_sip_res( struct sip_msg* msg,
2399
  unsigned int *returned_len, const struct socket_info *sock,int flags)
2400
0
{
2401
0
  unsigned int new_len, body_delta, len;
2402
0
  char *new_buf, *buf;
2403
0
  unsigned int offset, s_offset;
2404
0
  str body;
2405
2406
0
  buf=msg->buf;
2407
0
  len=msg->len;
2408
0
  new_buf=0;
2409
2410
  /* Calculate message body difference and adjust
2411
   * Content-Length
2412
   */
2413
0
  body_delta = calculate_body_diff( msg, sock);
2414
0
  if (adjust_clen(msg, body_delta, (msg->via2? msg->via2->proto:PROTO_UDP))
2415
0
      < 0) {
2416
0
    LM_ERR("failed to adjust Content-Length\n");
2417
0
    goto error;
2418
0
  }
2419
2420
  /* remove the first via */
2421
0
  if (!(flags & MSG_TRANS_NOVIA_FLAG)) {
2422
0
    unsigned int via_len, via_offset;
2423
2424
0
    if (msg->via1->next) {
2425
0
      via_len = msg->via1->bsize;
2426
0
      via_offset = msg->h_via1->body.s-buf;
2427
0
    } else {
2428
0
      via_len = msg->h_via1->len;
2429
0
      via_offset = msg->h_via1->name.s-buf;
2430
0
    }
2431
2432
0
    if (del_lump(msg, via_offset, via_len, HDR_VIA_T) == 0) {
2433
0
      LM_ERR("failed to remove first via\n");
2434
0
      goto error;
2435
0
    }
2436
0
  }
2437
2438
  /* adjust len to the useful part of the message */
2439
0
  if (get_body(msg, &body) == 0 && body.len)
2440
0
    len -= (msg->buf + msg->len - body.s - body.len);
2441
0
  new_len=len+body_delta+lumps_len(msg, msg->add_rm, sock, -1);
2442
2443
0
  LM_DBG(" old size: %d, new size: %d\n", len, new_len);
2444
0
  new_buf=(char*)pkg_malloc(new_len+1); /* +1 is for debugging
2445
                       (\0 to print it )*/
2446
0
  if (new_buf==0){
2447
0
    LM_ERR("out of pkg mem\n");
2448
0
    goto error;
2449
0
  }
2450
0
  offset=s_offset=0;
2451
2452
  /* apply changes over SIP hdrs and body */
2453
0
  apply_msg_changes( msg, new_buf, &offset, &s_offset, sock, len);
2454
0
  if (offset!=new_len) {
2455
0
    LM_BUG("len mismatch : calculated %d, written %d\n", new_len, offset);
2456
0
    abort();
2457
0
  }
2458
2459
0
  new_buf[new_len]=0; /* debug: print the message */
2460
2461
  /* as it is a relaied reply, if 503, make it 500 (just reply code) */
2462
0
  if ( !disable_503_translation && msg->first_line.u.reply.statuscode==503 )
2463
0
    new_buf[(int)(msg->first_line.u.reply.status.s-msg->buf)+2] = '0';
2464
  /* send it! */
2465
0
  LM_DBG("copied size: orig:%d, new: %d, rest: %d"
2466
0
      " msg=|\n%s|\n", s_offset, offset, len-s_offset, new_buf);
2467
2468
0
  *returned_len=new_len;
2469
0
  return new_buf;
2470
0
error:
2471
0
  *returned_len=0;
2472
0
  return 0;
2473
0
}
2474
2475
2476
char * build_res_buf_from_sip_req( unsigned int code, const str *text ,str *new_tag,
2477
    struct sip_msg* msg, unsigned int *returned_len, struct bookmark *bmark)
2478
0
{
2479
0
  char *buf, *p, *received_buf, *rport_buf, *warning_buf;
2480
0
  char *content_len_buf, *after_body, *totags;
2481
0
  unsigned int len, foo, received_len, rport_len;
2482
0
  unsigned int warning_len, content_len_len;
2483
0
  struct hdr_field *hdr;
2484
0
  struct lump_rpl *lump, *body;
2485
0
  int i;
2486
0
  str to_tag;
2487
2488
0
  body = 0;
2489
0
  buf=0;
2490
0
  to_tag.s = 0;
2491
0
  to_tag.len = 0;
2492
0
  received_buf=rport_buf=warning_buf=content_len_buf=0;
2493
0
  received_len=rport_len=warning_len=content_len_len=0;
2494
2495
  /* force parsing all headers -- we want to return all
2496
  Via's in the reply and they may be scattered down to the
2497
  end of header (non-block Vias are a really poor property
2498
  of SIP :( ) */
2499
0
  if (parse_headers( msg, HDR_EOH_F, 0 )==-1) {
2500
0
    LM_ERR("parse_headers failed\n");
2501
0
    goto error00;
2502
0
  }
2503
2504
  /*computes the length of the new response buffer*/
2505
0
  len = 0;
2506
2507
  /* check if rport needs to be updated */
2508
0
  if ( (msg->msg_flags&FL_FORCE_RPORT)||
2509
0
    (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)){
2510
0
    if ((rport_buf=rport_builder(msg, &rport_len))==0){
2511
0
      LM_ERR("rport_builder failed\n");
2512
0
      goto error00;
2513
0
    }
2514
0
    if (msg->via1->rport)
2515
0
      len -= msg->via1->rport->size+1; /* include ';' */
2516
0
  }
2517
2518
  /* check if received needs to be added or via rport has to be added */
2519
0
  if (rport_buf || received_test(msg)) {
2520
0
    if ((received_buf=received_builder(msg,&received_len))==0) {
2521
0
      LM_ERR("received_builder failed\n");
2522
0
      goto error01;
2523
0
    }
2524
0
  }
2525
2526
  /* first line */
2527
0
  len += SIP_VERSION_LEN + 1/*space*/ + 3/*code*/ + 1/*space*/ +
2528
0
    text->len + CRLF_LEN/*new line*/;
2529
  /* copy the TO hdr */
2530
0
  if (msg->to) {
2531
0
    if (new_tag && new_tag->len) {
2532
0
      to_tag=get_to(msg)->tag_value;
2533
0
      if (to_tag.len )
2534
0
        len+=new_tag->len-to_tag.len;
2535
0
      else
2536
0
        len+=new_tag->len+TOTAG_TOKEN_LEN/*";tag="*/;
2537
0
    }
2538
0
    len += msg->to->len;
2539
0
  }
2540
2541
  /* copy all VIA hdrs */
2542
0
  for( hdr=msg->h_via1 ; hdr ; hdr=hdr->sibling) {
2543
    /* we always add CRLF to via*/
2544
0
    len+=(hdr->body.s+hdr->body.len)-hdr->name.s+CRLF_LEN;
2545
0
    if (hdr==msg->h_via1) len += received_len+rport_len;
2546
0
  }
2547
  /* copy all Record-Route hdrs */
2548
0
  for( hdr=msg->record_route ; hdr ; hdr=hdr->sibling) {
2549
    /* RR only for 1xx and 2xx replies */
2550
0
    if (code>=180 && code<300)
2551
0
      len += hdr->len;
2552
0
  }
2553
  /* copy the FROM hdr */
2554
0
  if (msg->from)
2555
0
    len += msg->from->len;
2556
  /* copy the CALLID hdr */
2557
0
  if (msg->callid)
2558
0
    len += msg->callid->len;
2559
  /* copy the CSEQ hdr */
2560
0
  if (msg->cseq)
2561
0
    len += msg->cseq->len;
2562
2563
  /* lumps length */
2564
0
  for(lump=msg->reply_lump;lump;lump=lump->next) {
2565
0
    len += lump->text.len;
2566
0
    if (lump->flags&LUMP_RPL_BODY)
2567
0
      body = lump;
2568
0
  }
2569
  /* server header */
2570
0
  if (server_signature)
2571
0
    len += server_header->len + CRLF_LEN;
2572
  /* warning hdr */
2573
0
  if (sip_warning) {
2574
0
    warning_buf = warning_builder(msg,&warning_len);
2575
0
    if (warning_buf) len += warning_len + CRLF_LEN;
2576
0
    else LM_WARN("warning skipped -- too big\n");
2577
0
  }
2578
  /* content length hdr */
2579
0
  if (body) {
2580
0
    content_len_buf = int2str(body->text.len, (int*)&content_len_len);
2581
0
    len += CONTENT_LENGTH_LEN + content_len_len + CRLF_LEN;
2582
0
  } else {
2583
0
    len += CONTENT_LENGTH_LEN + 1/*0*/ + CRLF_LEN;
2584
0
  }
2585
  /* end of message */
2586
0
  len += CRLF_LEN; /*new line*/
2587
2588
  /*allocating mem*/
2589
0
  buf = (char*) pkg_malloc( len+1 );
2590
0
  if (!buf)
2591
0
  {
2592
0
    LM_ERR("out of pkg memory; needs %d\n",len);
2593
0
    goto error01;
2594
0
  }
2595
2596
  /* filling the buffer*/
2597
0
  p=buf;
2598
  /* first line */
2599
0
  memcpy( p , SIP_VERSION , SIP_VERSION_LEN );
2600
0
  p += SIP_VERSION_LEN;
2601
0
  *(p++) = ' ' ;
2602
  /*code*/
2603
0
  for ( i=2 , foo = code  ;  i>=0  ;  i-- , foo=foo/10 )
2604
0
    *(p+i) = '0' + foo - ( foo/10 )*10;
2605
0
  p += 3;
2606
0
  *(p++) = ' ' ;
2607
0
  memcpy( p , text->s , text->len );
2608
0
  p += text->len;
2609
0
  memcpy( p, CRLF, CRLF_LEN );
2610
0
  p+=CRLF_LEN;
2611
  /* VIA headers */
2612
0
  if ( (hdr=msg->h_via1)!=NULL ) {
2613
    /* handle the VIA1, subject to changes */
2614
0
    i = 0;
2615
0
    if (received_buf) {
2616
0
      i = msg->via1->host.s - msg->via1->hdr.s +
2617
0
        msg->via1->host.len + (msg->via1->port?
2618
0
        msg->via1->port_str.len + 1 : 0);
2619
      /* copy via1 up to params */
2620
0
      append_str( p, hdr->name.s, i);
2621
      /* copy received param */
2622
0
      append_str( p, received_buf, received_len);
2623
0
    }
2624
0
    if (rport_buf){
2625
0
      if (msg->via1->rport){ /* delete the old one */
2626
        /* copy until rport */
2627
0
        append_str( p, hdr->name.s+i ,
2628
0
          msg->via1->rport->start-hdr->name.s-1-i);
2629
        /* copy new rport */
2630
0
        append_str(p, rport_buf, rport_len);
2631
        /* copy the rest of the via */
2632
0
        append_str(p, msg->via1->rport->start+
2633
0
                  msg->via1->rport->size,
2634
0
                  hdr->body.s+hdr->body.len-
2635
0
                  msg->via1->rport->start-
2636
0
                  msg->via1->rport->size);
2637
0
      }else{ /* just copy rport and rest of hdr */
2638
0
        append_str(p, rport_buf, rport_len);
2639
0
        append_str( p, hdr->name.s+i ,
2640
0
          (hdr->body.s+hdr->body.len)-hdr->name.s-i);
2641
0
      }
2642
0
    }else{
2643
      /* normal whole via copy */
2644
0
      append_str( p, hdr->name.s+i ,
2645
0
        (hdr->body.s+hdr->body.len)-hdr->name.s-i);
2646
0
    }
2647
0
    append_str( p, CRLF,CRLF_LEN);
2648
    /* and now the rest of the VIA hdrs */
2649
0
    for( hdr=hdr->sibling ; hdr ; hdr=hdr->sibling) {
2650
      /* normal whole via copy */
2651
0
      append_str( p, hdr->name.s,
2652
0
          (hdr->body.s+hdr->body.len)-hdr->name.s);
2653
0
      append_str( p, CRLF,CRLF_LEN);
2654
0
    }
2655
0
  }
2656
  /* Record-Route headers */
2657
0
  for( hdr=msg->record_route ; hdr ; hdr=hdr->sibling) {
2658
    /* RR only for 1xx and 2xx replies */
2659
0
    if (code>=180 && code<300)
2660
0
      append_str(p, hdr->name.s, hdr->len);
2661
0
  }
2662
  /* TO hdr */
2663
0
  if ( (hdr=msg->to)!=NULL ) {
2664
0
    if (new_tag && new_tag->len){
2665
0
      if (to_tag.len ) { /* replacement */
2666
        /* before to-tag */
2667
0
        append_str( p, hdr->name.s, to_tag.s-hdr->name.s);
2668
        /* to tag replacement */
2669
0
        bmark->to_tag_val.s=p;
2670
0
        bmark->to_tag_val.len=new_tag->len;
2671
0
        append_str( p, new_tag->s,new_tag->len);
2672
        /* the rest after to-tag */
2673
0
        append_str( p, to_tag.s+to_tag.len,
2674
0
          hdr->name.s+hdr->len-(to_tag.s+to_tag.len));
2675
0
      }else{ /* adding a new to-tag */
2676
0
        after_body=hdr->body.s+hdr->body.len;
2677
0
        append_str( p, hdr->name.s, after_body-hdr->name.s);
2678
0
        append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN);
2679
0
        bmark->to_tag_val.s=p;
2680
0
        bmark->to_tag_val.len=new_tag->len;
2681
0
        append_str( p, new_tag->s,new_tag->len);
2682
0
        append_str( p, after_body,
2683
0
                hdr->name.s+hdr->len-after_body);
2684
0
      }
2685
0
    } else {
2686
      /* no new to-tag -- proceed to 1:1 copying  */
2687
0
      totags=((struct to_body*)(hdr->parsed))->tag_value.s;
2688
0
      if (totags) {
2689
0
        bmark->to_tag_val.s=p+(totags-hdr->name.s);
2690
0
        bmark->to_tag_val.len=
2691
0
          ((struct to_body*)(hdr->parsed))->tag_value.len;
2692
0
      } else {
2693
0
        bmark->to_tag_val.s = NULL;
2694
0
        bmark->to_tag_val.len = 0;
2695
0
      }
2696
0
      append_str(p, hdr->name.s, hdr->len);
2697
0
    }
2698
0
  }
2699
  /* FROM header */
2700
0
  if (msg->from)
2701
0
    append_str(p, msg->from->name.s, msg->from->len);
2702
  /* CALLID header */
2703
0
  if (msg->callid)
2704
0
    append_str(p, msg->callid->name.s, msg->callid->len);
2705
  /* copy the CSEQ hdr */
2706
0
  if (msg->cseq)
2707
0
    append_str(p, msg->cseq->name.s, msg->cseq->len);
2708
  /* lumps */
2709
0
  for(lump=msg->reply_lump;lump;lump=lump->next)
2710
0
    if (lump->flags&LUMP_RPL_HDR){
2711
0
      memcpy(p,lump->text.s,lump->text.len);
2712
0
      p += lump->text.len;
2713
0
    }
2714
  /* server header */
2715
0
  if (server_signature) {
2716
0
    append_str( p, server_header->s, server_header->len);
2717
0
    append_str( p, CRLF, CRLF_LEN );
2718
0
  }
2719
  /* content_length hdr */
2720
0
  if (content_len_len) {
2721
0
    append_str( p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
2722
0
    append_str( p, content_len_buf, content_len_len );
2723
0
    append_str( p, CRLF, CRLF_LEN );
2724
0
  } else {
2725
0
    append_str( p, CONTENT_LENGTH"0"CRLF,CONTENT_LENGTH_LEN+1+CRLF_LEN);
2726
0
  }
2727
  /* warning header */
2728
0
  if (warning_buf) {
2729
0
    append_str( p, warning_buf, warning_len );
2730
0
    append_str( p, CRLF, CRLF_LEN );
2731
0
  }
2732
  /*end of message*/
2733
0
  memcpy( p, CRLF, CRLF_LEN );
2734
0
  p+=CRLF_LEN;
2735
  /* body */
2736
0
  if (body) {
2737
0
    append_str( p, body->text.s, body->text.len );
2738
0
  }
2739
2740
0
  if (len!=(unsigned long)(p-buf))
2741
0
    LM_CRIT("diff len=%d p-buf=%d\n", len, (int)(p-buf));
2742
2743
0
  *(p) = 0;
2744
0
  *returned_len = len;
2745
  /* in req2reply, received_buf is not introduced to lumps and
2746
     needs to be deleted here
2747
  */
2748
0
  if (received_buf) pkg_free(received_buf);
2749
0
  if (rport_buf) pkg_free(rport_buf);
2750
0
  return buf;
2751
2752
0
error01:
2753
0
  if (received_buf) pkg_free(received_buf);
2754
0
  if (rport_buf) pkg_free(rport_buf);
2755
0
error00:
2756
0
  *returned_len=0;
2757
0
  return 0;
2758
0
}
2759
2760
2761
2762
/*! \brief return number of chars printed or 0 if space exceeded;
2763
   assumes buffer size of at least MAX_BRANCH_PARAM_LEN
2764
 */
2765
int branch_builder( unsigned int hash_index,
2766
  /* only either parameter useful */
2767
  unsigned int label, char * char_v,
2768
  int branch,
2769
  char *branch_str, int *len )
2770
0
{
2771
2772
0
  char *begin;
2773
0
  int size;
2774
2775
  /* hash id provided ... start with it */
2776
0
  size=MAX_BRANCH_PARAM_LEN;
2777
0
  begin=branch_str;
2778
0
  *len=0;
2779
2780
0
  memcpy(begin, MCOOKIE, MCOOKIE_LEN );
2781
0
  size-=MCOOKIE_LEN;begin+=MCOOKIE_LEN;
2782
2783
0
  if (int2reverse_hex( &begin, &size, hash_index)==-1)
2784
0
    return 0;
2785
2786
0
  if (size) {
2787
0
    *begin=BRANCH_SEPARATOR;
2788
0
    begin++; size--;
2789
0
  } else return 0;
2790
2791
  /* string with request's characteristic value ... use it ... */
2792
0
  if (char_v) {
2793
0
    if (memcpy(begin,char_v,MD5_LEN)) {
2794
0
      begin+=MD5_LEN; size-=MD5_LEN;
2795
0
    } else return 0;
2796
0
  } else { /* ... use the "label" value otherwise */
2797
0
    if (int2reverse_hex( &begin, &size, label )==-1)
2798
0
      return 0;
2799
0
  }
2800
2801
0
  if (size) {
2802
0
    *begin=BRANCH_SEPARATOR;
2803
0
    begin++; size--;
2804
0
  } else return 0;
2805
2806
0
  if (int2reverse_hex( &begin, &size, branch)==-1)
2807
0
    return 0;
2808
2809
0
  *len=MAX_BRANCH_PARAM_LEN-size;
2810
0
  return size;
2811
2812
0
}
2813
2814
2815
char* via_builder( unsigned int *len,
2816
  const struct socket_info* send_sock,
2817
  str* branch, str* extra_params, int proto, struct hostport* hp)
2818
0
{
2819
0
  unsigned int via_len, extra_len;
2820
0
  char *line_buf;
2821
0
  int max_len, local_via_len=MY_VIA_LEN;
2822
0
  const str* address_str; /* address displayed in via */
2823
0
  const str* port_str; /* port no displayed in via */
2824
2825
  /* use pre-set address in via or the outbound socket one */
2826
0
  if (hp && hp->host && hp->host->len)
2827
0
    address_str=hp->host;
2828
0
  else
2829
0
    address_str=get_adv_host(send_sock);
2830
2831
0
  if (hp && hp->port && hp->port->len)
2832
0
    port_str=hp->port;
2833
0
  else
2834
0
    port_str=get_adv_port(send_sock);
2835
2836
0
  max_len=local_via_len+address_str->len /* space in MY_VIA */
2837
0
    +2 /* just in case it is a v6 address ... [ ] */
2838
0
    +1 /*':'*/+port_str->len
2839
0
    +(branch?(MY_BRANCH_LEN+branch->len):0)
2840
0
    +(extra_params?extra_params->len:0)
2841
0
    +CRLF_LEN+1;
2842
0
  line_buf=pkg_malloc( max_len );
2843
0
  if (line_buf==0){
2844
0
    ser_error=E_OUT_OF_MEM;
2845
0
    LM_ERR("out of pkg memory\n");
2846
0
    return 0;
2847
0
  }
2848
2849
0
  extra_len=0;
2850
2851
0
  memcpy(line_buf, MY_VIA, local_via_len);
2852
0
  if (proto==PROTO_UDP){
2853
    /* do nothing */
2854
0
  }else if (proto==PROTO_TCP){
2855
0
    memcpy(line_buf+local_via_len-4, "TCP ", 4);
2856
0
  }else if (proto==PROTO_TLS){
2857
0
    memcpy(line_buf+local_via_len-4, "TLS ", 4);
2858
0
  }else if(proto==PROTO_SCTP){
2859
0
    memcpy(line_buf+local_via_len-4, "SCTP ", 5);
2860
0
    local_via_len++;
2861
0
  }else if(proto==PROTO_WS){
2862
0
    memcpy(line_buf+local_via_len-4, "WS ", 3);
2863
0
    local_via_len--;
2864
0
  }else if(proto==PROTO_WSS){
2865
0
    memcpy(line_buf+local_via_len-4, "WSS ", 4);
2866
0
  }else{
2867
0
    LM_CRIT("unknown proto %d\n", proto);
2868
0
    return 0;
2869
0
  }
2870
2871
0
  via_len=local_via_len+address_str->len; /*space included in MY_VIA*/
2872
2873
0
  memcpy(line_buf+local_via_len+extra_len, address_str->s, address_str->len);
2874
0
  line_buf[via_len]=':'; via_len++;
2875
0
  memcpy(line_buf+via_len, port_str->s, port_str->len);
2876
0
  via_len+=port_str->len;
2877
2878
  /* branch parameter */
2879
0
  if (branch){
2880
0
    memcpy(line_buf+via_len, MY_BRANCH, MY_BRANCH_LEN );
2881
0
    via_len+=MY_BRANCH_LEN;
2882
0
    memcpy(line_buf+via_len, branch->s, branch->len );
2883
0
    via_len+=branch->len;
2884
0
  }
2885
  /* extra params  */
2886
0
  if (extra_params){
2887
0
    memcpy(line_buf+via_len, extra_params->s, extra_params->len);
2888
0
    via_len+=extra_params->len;
2889
0
  }
2890
2891
0
  memcpy(line_buf+via_len, CRLF, CRLF_LEN);
2892
0
  via_len+=CRLF_LEN;
2893
0
  line_buf[via_len]=0; /* null terminate the string*/
2894
2895
0
  *len = via_len;
2896
0
  return line_buf;
2897
0
}
2898
2899
#define MAX_URI_LEN   1024
2900
static char uri_buff[MAX_URI_LEN];
2901
char *construct_uri(str *protocol,str *username,str *domain,str *port,
2902
    str *params,int *len)
2903
0
{
2904
0
  int pos = 0;
2905
2906
0
  if (!len)
2907
0
  {
2908
0
    LM_ERR("null pointer provided for construct_uri \n");
2909
0
    return 0;
2910
0
  }
2911
2912
0
  if (!protocol->s || protocol->len == 0)
2913
0
  {
2914
0
    LM_ERR("no protocol specified\n");
2915
0
    return 0;
2916
0
  }
2917
2918
0
  if (!domain->s || domain->len == 0)
2919
0
  {
2920
0
    LM_ERR("no domain specified\n");
2921
0
    return 0;
2922
0
  }
2923
2924
0
  memcpy(uri_buff,protocol->s,protocol->len);
2925
0
  pos += protocol->len;
2926
0
  uri_buff[pos++] = ':';
2927
2928
0
  if (username && username->s && username->len != 0)
2929
0
  {
2930
0
    memcpy(uri_buff+pos,username->s,username->len);
2931
0
    pos += username->len;
2932
0
    uri_buff[pos++] = '@';
2933
0
  }
2934
2935
0
  memcpy(uri_buff+pos,domain->s,domain->len);
2936
0
  pos += domain->len;
2937
2938
0
  if (port && port->s && port->len !=0)
2939
0
  {
2940
0
    uri_buff[pos++] = ':';
2941
0
    memcpy(uri_buff+pos,port->s,port->len);
2942
0
    pos += port->len;
2943
0
  }
2944
2945
0
  if (params && params->s && params->len !=0 )
2946
0
  {
2947
0
    uri_buff[pos++] = ';';
2948
0
    memcpy(uri_buff+pos,params->s,params->len);
2949
0
    pos += params->len;
2950
0
  }
2951
2952
0
  uri_buff[pos] = 0;
2953
0
  *len = pos;
2954
0
  return uri_buff;
2955
0
}
2956
2957
/* uses uri_buff above, since contact is still an uri */
2958
char *contact_builder(const struct socket_info* send_sock, int *ct_len)
2959
0
{
2960
0
  char *p;
2961
0
  int proto_len = 0;
2962
0
  const str* address_str = get_adv_host(send_sock);
2963
0
  const str* port_str = get_adv_port(send_sock);
2964
2965
  /* sip: */
2966
0
  p = uri_buff;
2967
0
  memcpy(p, "sip:", 4);
2968
0
  p += 4;
2969
2970
  /* host */
2971
0
  memcpy(p, address_str->s, address_str->len);
2972
0
  p += address_str->len;
2973
2974
  /* :port */
2975
0
  *p++ = ':';
2976
0
  memcpy(p, port_str->s, port_str->len);
2977
0
  p += port_str->len;
2978
2979
  /* transport if needed */
2980
0
  if (send_sock->proto != PROTO_UDP) {
2981
0
    memcpy(p, ";transport=", 11);
2982
0
    p += 11;
2983
0
    proto_len = strlen(protos[send_sock->proto].name);
2984
0
    memcpy(p, protos[send_sock->proto].name, proto_len);
2985
0
    p += proto_len;
2986
0
  }
2987
2988
0
  *p = '\0';
2989
2990
0
  if (ct_len)
2991
0
    *ct_len = p - uri_buff;
2992
2993
0
  return uri_buff;
2994
0
}