Coverage Report

Created: 2025-04-11 06:59

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