2 * Copyright (C) 2001-2003 FhG Fokus
4 * This file is part of Kamailio, a free SIP server.
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
11 * Kamailio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 /** Via special params:
25 * - if the address in via is different from the src_ip or an existing
26 * received=something is found, received=src_ip is added (and any preexisting
27 * received is deleted). received is added as the first via parameter if no
28 * receive is previously present or over the old receive.
29 * - if the original via contains rport / rport=something or msg->msg_flags
30 * FL_FORCE_RPORT is set (e.g. script force_rport() cmd) rport=src_port
31 * is added (over previous rport / as first via param or after received
32 * if no received was present and received is added too)
34 * (see also sl_send_reply)
35 * - rport and received are added in mostly the same way as for requests, but
36 * in the reverse order (first rport and then received). See also
38 * - if reply_to_via is set (default off) the local reply will be sent to
39 * the address in via (received is ignored since it was not set by us). The
40 * destination port is either the message source port if via contains rport
41 * or the FL_FORCE_RPORT flag is set or the port from the via. If either
42 * port or rport are present a normal dns lookup (instead of a srv lookup)
43 * is performed on the address. If no port is present and a srv lookup is
44 * performed the port is taken from the srv lookup. If the srv lookup failed
45 * or it was not performed, the port is set to the default sip port (5060).
46 * - if reply_to_via is off (default) the local reply is sent to the message
47 * source ip address. The destination port is set to the source port if
48 * rport is present or FL_FORCE_RPORT flag is set, to the via port or to
49 * the default sip port (5060) if neither rport or via port are present.
51 * - if received is present the message is sent to the received address else
52 * if no port is present (neither a normal via port or rport) a dns srv
53 * lookup is performed on the host part and the reply is sent to the
54 * resulting ip. If a port is present or the host part is an ip address
55 * the dns lookup will be a "normal" one (A or AAAA).
56 * - if rport is present, it's value will be used as the destination port
57 * (and this will also disable srv lookups)
58 * - if no port is present the destination port will be taken from the srv
59 * lookup. If the srv lookup fails or is not performed (e.g. ip address
60 * in host) the destination port will be set to the default sip port (5060).
63 * - when locally replying to a message, rport and received will be appended to
64 * the via header parameters (for forwarded requests they are inserted at the
66 * - a locally generated reply might get two received via parameters if a
67 * received is already present in the original message (this should not
68 * happen though, but ...)
75 * \brief Kamailio core :: Message translations
80 #include <sys/types.h>
81 #include <sys/socket.h>
87 #include "comp_defs.h"
88 #include "msg_translator.h"
95 #include "data_lump.h"
96 #include "data_lump_rpl.h"
102 #include "parser/parse_to.h"
103 #include "parser/parse_param.h"
105 #include "str_list.h"
106 #include "rand/kam_rand.h"
108 #define append_str_trans(_dest,_src,_len,_msg) \
109 append_str( (_dest), (_src), (_len) );
111 extern char version[];
112 extern int version_len;
116 /** per process fixup function for global_req_flags.
117 * It should be called from the configuration framework.
119 void fix_global_req_flags(str* gname, str* name)
122 switch(cfg_get(core, core_cfg, udp_mtu_try_proto)){
128 global_req_flags|=FL_MTU_TCP_FB;
131 global_req_flags|=FL_MTU_TLS_FB;
134 global_req_flags|=FL_MTU_SCTP_FB;
137 if (cfg_get(core, core_cfg, force_rport))
138 global_req_flags|=FL_FORCE_RPORT;
143 /* checks if ip is in host(name) and ?host(ip)=name?
144 * ip must be in network byte order!
145 * resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made
146 * return 0 if equal */
147 static int check_via_address(struct ip_addr* ip, str *name,
148 unsigned short port, int resolver)
156 /* maybe we are lucky and name it's an ip */
159 LM_DBG("(%s, %.*s, %d)\n", s, name->len, name->s, resolver);
163 /* check if name->s is an ipv6 address or an ipv6 address ref. */
164 if ((ip->af==AF_INET6) &&
165 ( ((len==name->len)&&(strncasecmp(name->s, s, name->len)==0))
167 ((len==(name->len-2))&&(name->s[0]=='[')&&
168 (name->s[name->len-1]==']')&&
169 (strncasecmp(name->s+1, s, len)==0))
175 if (strncmp(name->s, s, name->len)==0)
178 LM_CRIT("could not convert ip address\n");
182 if (port==0) port=SIP_PORT;
183 if (resolver&DO_DNS){
184 LM_DBG("doing dns lookup\n");
185 /* try all names ips */
187 he=sip_resolvehost(name, &port, &lproto); /* don't use naptr */
188 if (he && ip->af==he->h_addrtype){
189 for(i=0;he && he->h_addr_list[i];i++){
190 if ( memcmp(&he->h_addr_list[i], ip->u.addr, ip->len)==0)
195 if (resolver&DO_REV_DNS){
196 LM_DBG("doing rev. dns lookup\n");
197 /* try reverse dns */
198 he=rev_resolvehost(ip);
199 if (he && (strncmp(he->h_name, name->s, name->len)==0))
201 for (i=0; he && he->h_aliases[i];i++){
202 if (strncmp(he->h_aliases[i],name->s, name->len)==0)
210 /* check if IP address in Via != source IP address of signaling,
211 * or the sender requires adding rport or received values */
212 int received_test( struct sip_msg *msg )
216 rcvd=msg->via1->received || msg->via1->rport
217 || check_via_address(&msg->rcv.src_ip, &msg->via1->host,
218 msg->via1->port, received_dns);
222 /* check if IP address in Via != source IP address of signaling */
223 int received_via_test( struct sip_msg *msg )
227 rcvd = (check_via_address(&msg->rcv.src_ip, &msg->via1->host,
228 msg->via1->port, received_dns)!=0);
232 static char * warning_builder( struct sip_msg *msg, unsigned int *returned_len)
234 static char buf[MAX_WARNING_LEN];
240 #define str_print(string, string_len) \
243 if ((clen+l)>MAX_WARNING_LEN) \
244 goto error_overflow; \
245 memcpy(buf+clen, (string), l); \
249 #define str_lenpair_print(string, string_len, string2, string2_len) \
251 str_print(string, string_len); \
252 str_print(string2, string2_len);\
255 #define str_pair_print( string, string2, string2_len) \
256 str_lenpair_print((string), strlen((string)), (string2), (string2_len))
258 #define str_int_print(string, intval)\
260 t=int2str((intval), &print_len); \
261 str_pair_print(string, t, print_len);\
264 #define str_su_print(sockaddr)\
266 t=su2a(&sockaddr, sizeof(sockaddr)); \
267 print_len=strlen(t); \
268 str_print(t, print_len); \
271 #define str_ipaddr_print(string, ipaddr_val)\
273 t=ip_addr2a((ipaddr_val)); \
274 print_len=strlen(t); \
275 str_pair_print(string, t, print_len);\
279 str_print(WARNING, WARNING_LEN);
280 str_su_print(msg->rcv.bind_address->su);
281 str_print(WARNING_PHRASE, WARNING_PHRASE_LEN);
287 foo=&(msg->first_line.u.request.uri);
289 str_int_print(" pid=", my_pid());
291 str_ipaddr_print(" req_src_ip=", &msg->rcv.src_ip);
292 str_int_print(" req_src_port=", msg->rcv.src_port);
293 str_pair_print(" in_uri=", msg->first_line.u.request.uri.s,
294 msg->first_line.u.request.uri.len);
295 str_pair_print(" out_uri=", foo->s, foo->len);
296 str_pair_print(" via_cnt",
297 (msg->parsed_flag & HDR_EOH_F)==HDR_EOH_F ? "=" : ">", 1);
298 str_int_print("=", via_cnt);
299 if (clen<MAX_WARNING_LEN){ buf[clen]='"'; clen++; }
300 else goto error_overflow;
306 LM_NOTICE("buffer size exceeded (probably too long URI)\n");
314 char* received_builder(struct sip_msg *msg, unsigned int *received_len)
318 struct ip_addr *source_ip;
322 source_ip=&msg->rcv.src_ip;
324 buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
326 ser_error=E_OUT_OF_MEM;
327 LM_ERR("out of memory\n");
330 memcpy(buf, RECEIVED, RECEIVED_LEN);
331 if ( (tmp=ip_addr2a(source_ip))==0) {
336 len=RECEIVED_LEN+tmp_len;
338 memcpy(buf+RECEIVED_LEN, tmp, tmp_len);
339 buf[len]=0; /*null terminate it */
347 char* rport_builder(struct sip_msg *msg, unsigned int *rport_len)
355 tmp=int2str(msg->rcv.src_port, &tmp_len);
356 len=RPORT_LEN+tmp_len;
357 buf=pkg_malloc(sizeof(char)*(len+1));/* space for null term */
359 ser_error=E_OUT_OF_MEM;
360 LM_ERR("out of memory\n");
363 memcpy(buf, RPORT, RPORT_LEN);
364 memcpy(buf+RPORT_LEN, tmp, tmp_len);
365 buf[len]=0; /*null terminate it*/
373 char* id_builder(struct sip_msg* msg, unsigned int *id_len)
377 char revhex[sizeof(int)*2];
383 if (int2reverse_hex(&p, &size, msg->rcv.proto_reserved1)==-1){
384 LM_CRIT("not enough space for id\n");
387 value_len=p-&revhex[0];
388 len=ID_PARAM_LEN+value_len;
389 buf=pkg_malloc(sizeof(char)*(len+1));/* place for ending \0 */
391 ser_error=E_OUT_OF_MEM;
392 LM_ERR("out of memory\n");
395 memcpy(buf, ID_PARAM, ID_PARAM_LEN);
396 memcpy(buf+ID_PARAM_LEN, revhex, value_len);
397 buf[len]=0; /* null terminate it */
404 char* clen_builder( struct sip_msg* msg, int *clen_len, int diff,
418 LM_ERR("no message body found (missing crlf?) [[%.*s]]\n",
422 value=msg->len-(int)(body-msg->buf)+diff;
423 value_s=int2str(value, &value_len);
424 LM_DBG("content-length: %d (%s)\n", value, value_s);
430 len=CONTENT_LENGTH_LEN+value_len+CRLF_LEN;
432 buf=pkg_malloc(sizeof(char)*(len+1));
434 ser_error=E_OUT_OF_MEM;
435 LM_ERR("out of memory\n");
439 memcpy(buf, value_s, value_len);
442 memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
443 memcpy(buf+CONTENT_LENGTH_LEN, value_s, value_len);
444 memcpy(buf+CONTENT_LENGTH_LEN+value_len, CRLF, CRLF_LEN);
446 buf[len]=0; /* null terminate it */
453 /* checks if a lump opt condition
454 * returns 1 if cond is true, 0 if false */
455 static inline int lump_check_opt( struct lump *l,
457 struct dest_info* snd_i
464 #define get_ip_port_proto \
465 if ((snd_i==0) || (snd_i->send_sock==0)){ \
466 LM_CRIT("null send socket\n"); \
467 return 1; /* we presume they are different :-) */ \
469 if (msg->rcv.bind_address){ \
470 ip=&msg->rcv.bind_address->address; \
471 port=msg->rcv.bind_address->port_no; \
472 proto=msg->rcv.bind_address->proto; \
474 ip=&msg->rcv.dst_ip; \
475 port=msg->rcv.dst_port; \
476 proto=msg->rcv.proto; \
483 LUMP_SET_COND_TRUE(l);
485 case COND_IF_DIFF_REALMS:
487 /* faster tests first */
488 if ((port==snd_i->send_sock->port_no) &&
489 (proto==snd_i->send_sock->proto) &&
491 (msg->rcv.comp==snd_i->comp) &&
493 (ip_addr_cmp(ip, &snd_i->send_sock->address)))
496 LUMP_SET_COND_TRUE(l);
499 case COND_IF_DIFF_AF:
501 if (ip->af!=snd_i->send_sock->address.af) {
502 LUMP_SET_COND_TRUE(l);
505 case COND_IF_DIFF_PROTO:
507 if (proto!=snd_i->send_sock->proto) {
508 LUMP_SET_COND_TRUE(l);
511 case COND_IF_DIFF_PORT:
513 if (port!=snd_i->send_sock->port_no) {
514 LUMP_SET_COND_TRUE(l);
517 case COND_IF_DIFF_IP:
519 if (ip_addr_cmp(ip, &snd_i->send_sock->address)) return 0;
521 LUMP_SET_COND_TRUE(l);
525 if(kam_rand()>=KAM_RAND_MAX/2) {
526 LUMP_SET_COND_TRUE(l);
530 LM_CRIT("unknown lump condition %d\n", l->u.cond);
532 return 0; /* false */
537 /* computes the "unpacked" len of a lump list,
538 code moved from build_req_from_req */
539 static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
540 struct dest_info* send_info)
546 str* send_address_str;
548 str* recv_address_str = NULL;
549 str* recv_port_str = NULL;
550 int recv_port_no = 0;
551 struct socket_info* send_sock;
555 #define RCVCOMP_LUMP_LEN \
557 switch(msg->rcv.comp){ \
561 new_len+=COMP_PARAM_LEN+SIGCOMP_NAME_LEN; \
564 new_len+=COMP_PARAM_LEN+SERGZ_NAME_LEN ; \
567 LM_CRIT("unknown comp %d\n", msg->rcv.comp); \
570 #define SENDCOMP_LUMP_LEN \
572 switch(send_info->comp){ \
576 new_len+=COMP_PARAM_LEN+SIGCOMP_NAME_LEN; \
579 new_len+=COMP_PARAM_LEN+SERGZ_NAME_LEN ; \
582 LM_CRIT("unknown comp %d\n", send_info->comp); \
585 #define RCVCOMP_LUMP_LEN
586 #define SENDCOMP_LUMP_LEN
589 #define SUBST_LUMP_LEN(subst_l) \
590 switch((subst_l)->u.subst){ \
592 if (msg->rcv.bind_address){ \
593 new_len+=recv_address_str->len; \
594 if (msg->rcv.bind_address->address.af!=AF_INET) \
598 LM_CRIT("FIXME: null bind_address\n"); \
601 case SUBST_RCV_PORT: \
602 if (msg->rcv.bind_address){ \
603 new_len+=recv_port_str->len; \
606 LM_CRIT("FIXME: null bind_address\n"); \
609 case SUBST_RCV_PROTO: \
610 if (msg->rcv.bind_address){ \
611 switch(msg->rcv.bind_address->proto){ \
618 switch(msg->rcv.proto){ \
632 LM_CRIT("unknown proto %d\n", msg->rcv.bind_address->proto); \
636 LM_CRIT("FIXME: null bind_address\n"); \
639 case SUBST_RCV_ALL: \
640 if (msg->rcv.bind_address){ \
641 new_len+=recv_address_str->len; \
642 if (msg->rcv.bind_address->address.af!=AF_INET) \
644 if (recv_port_no!=SIP_PORT){ \
646 new_len+=1+recv_port_str->len; \
648 /*add;transport=xxx*/ \
649 switch(msg->rcv.bind_address->proto){ \
652 break; /* udp is the default */ \
655 switch(msg->rcv.proto){ \
658 new_len+=TRANSPORT_PARAM_LEN+2; \
661 new_len+=TRANSPORT_PARAM_LEN+3; \
666 new_len+=TRANSPORT_PARAM_LEN+4; \
669 LM_CRIT("unknown proto %d\n", \
670 msg->rcv.bind_address->proto); \
675 LM_CRIT("FIXME: null bind_address\n"); \
680 new_len+=send_address_str->len; \
681 if (send_sock->address.af==AF_INET6 && \
682 send_address_str->s[0]!='[') \
685 LM_CRIT("FIXME: null send_sock\n"); \
688 case SUBST_SND_PORT: \
690 new_len+=send_port_str->len; \
692 LM_CRIT("FIXME: null send_sock\n"); \
695 case SUBST_SND_PROTO: \
697 switch(send_sock->proto){ \
704 switch(send_info->proto){ \
718 LM_CRIT("unknown proto %d\n", send_sock->proto); \
721 LM_CRIT("FIXME: null send_sock\n"); \
724 case SUBST_SND_ALL: \
726 new_len+=send_address_str->len; \
727 if ((send_sock->address.af==AF_INET6) && \
728 (send_address_str->s[0]!='[')) \
730 if ((send_sock->port_no!=SIP_PORT) || \
731 (send_port_str!=&(send_sock->port_no_str))){ \
733 new_len+=1+send_port_str->len; \
735 /*add;transport=xxx*/ \
736 switch(send_sock->proto){ \
739 break; /* udp is the default */ \
742 switch(send_info->proto){ \
745 new_len+=TRANSPORT_PARAM_LEN+2; \
748 new_len+=TRANSPORT_PARAM_LEN+3; \
753 new_len+=TRANSPORT_PARAM_LEN+4; \
756 LM_CRIT("unknown proto %d\n", send_sock->proto); \
761 LM_CRIT("FIXME: null send_sock\n"); \
764 case SUBST_NOP: /* do nothing */ \
767 LM_CRIT("unknown subst type %d\n", (subst_l)->u.subst); \
771 send_sock=send_info->send_sock;
777 /* init send_address_str & send_port_str */
778 if(send_sock && send_sock->useinfo.name.len>0)
779 send_address_str=&(send_sock->useinfo.name);
780 else if (msg->set_global_address.len)
781 send_address_str=&(msg->set_global_address);
783 send_address_str=&(send_sock->address_str);
784 if(send_sock && send_sock->useinfo.port_no>0)
785 send_port_str=&(send_sock->useinfo.port_no_str);
786 else if (msg->set_global_port.len)
787 send_port_str=&(msg->set_global_port);
789 send_port_str=&(send_sock->port_no_str);
790 /* init recv_address_str, recv_port_str & recv_port_no */
791 if(msg->rcv.bind_address) {
792 if(msg->rcv.bind_address->useinfo.name.len>0)
793 recv_address_str=&(msg->rcv.bind_address->useinfo.name);
795 recv_address_str=&(msg->rcv.bind_address->address_str);
796 if(msg->rcv.bind_address->useinfo.port_no>0) {
797 recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
798 recv_port_no = msg->rcv.bind_address->useinfo.port_no;
800 recv_port_str=&(msg->rcv.bind_address->port_no_str);
801 recv_port_no = msg->rcv.bind_address->port_no;
805 for(t=lumps;t;t=t->next){
806 /* skip if this is an OPT lump and the condition is not satisfied */
807 if ((t->op==LUMP_ADD_OPT)&& !lump_check_opt(t, msg, send_info))
809 for(r=t->before;r;r=r->before){
818 /* skip if this is an OPT lump and the condition is
820 if (!lump_check_opt(r, msg, send_info))
824 /* only ADD allowed for before/after */
825 LM_CRIT("invalid op for data lump (%x)\n", r->op);
837 /* we don't do anything here, it's only a condition for
841 /* fix overlapping deleted zones */
842 if (t->u.offset < s_offset){
844 if (t->len>s_offset-t->u.offset)
845 t->len-=s_offset-t->u.offset;
847 t->u.offset=s_offset;
849 s_offset=t->u.offset+t->len;
853 /* fix offset if overlapping on a deleted zone */
854 if (t->u.offset < s_offset){
855 t->u.offset=s_offset;
857 s_offset=t->u.offset;
861 LM_CRIT("invalid op for data lump (%x)\n", r->op);
863 for (r=t->after;r;r=r->after){
872 /* skip if this is an OPT lump and the condition is
874 if (!lump_check_opt(r, msg, send_info))
878 /* only ADD allowed for before/after */
879 LM_CRIT("invalid op for data lump (%x)\n", r->op);
883 ; /* to make gcc 3.* happy */
886 #undef RCVCOMP_LUMP_LEN
887 #undef SENDCOMP_LUMP_LEN
892 /* another helper functions, adds/Removes the lump,
893 code moved form build_req_from_req */
895 void process_lumps( struct sip_msg* msg,
898 unsigned int* new_buf_offs,
899 unsigned int* orig_offs,
900 struct dest_info* send_info,
909 str* send_address_str;
911 str* recv_address_str = NULL;
912 str* recv_port_str = NULL;
913 int recv_port_no = 0;
914 struct socket_info* send_sock;
917 #define RCVCOMP_PARAM_ADD \
918 /* add ;comp=xxxx */ \
919 switch(msg->rcv.comp){ \
923 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
924 offset+=COMP_PARAM_LEN; \
925 memcpy(new_buf+offset, SIGCOMP_NAME, \
927 offset+=SIGCOMP_NAME_LEN; \
930 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
931 offset+=COMP_PARAM_LEN; \
932 memcpy(new_buf+offset, SERGZ_NAME, SERGZ_NAME_LEN); \
933 offset+=SERGZ_NAME_LEN; \
936 LM_CRIT("unknown comp %d\n", msg->rcv.comp); \
939 #define SENDCOMP_PARAM_ADD \
940 /* add ;comp=xxxx */ \
941 switch(send_info->comp){ \
945 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
946 offset+=COMP_PARAM_LEN; \
947 memcpy(new_buf+offset, SIGCOMP_NAME, \
949 offset+=SIGCOMP_NAME_LEN; \
952 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
953 offset+=COMP_PARAM_LEN; \
954 memcpy(new_buf+offset, SERGZ_NAME, SERGZ_NAME_LEN); \
955 offset+=SERGZ_NAME_LEN; \
958 LM_CRIT("unknown comp %d\n", msg->rcv.comp); \
961 #define RCVCOMP_PARAM_ADD
962 #define SENDCOMP_PARAM_ADD
963 #endif /* USE_COMP */
965 #define SUBST_LUMP(subst_l) \
966 switch((subst_l)->u.subst){ \
968 if (msg->rcv.bind_address){ \
969 if (msg->rcv.bind_address->address.af!=AF_INET){\
970 new_buf[offset]='['; offset++; \
972 memcpy(new_buf+offset, recv_address_str->s, \
973 recv_address_str->len); \
974 offset+=recv_address_str->len; \
975 if (msg->rcv.bind_address->address.af!=AF_INET){\
976 new_buf[offset]=']'; offset++; \
980 LM_CRIT("FIXME: null bind_address\n"); \
983 case SUBST_RCV_PORT: \
984 if (msg->rcv.bind_address){ \
985 memcpy(new_buf+offset, recv_port_str->s, \
986 recv_port_str->len); \
987 offset+=recv_port_str->len; \
990 LM_CRIT("FIXME: null bind_address\n"); \
993 case SUBST_RCV_ALL: \
994 if (msg->rcv.bind_address){ \
996 if (msg->rcv.bind_address->address.af!=AF_INET){\
997 new_buf[offset]='['; offset++; \
999 memcpy(new_buf+offset, recv_address_str->s, \
1000 recv_address_str->len); \
1001 offset+=recv_address_str->len; \
1002 if (msg->rcv.bind_address->address.af!=AF_INET){\
1003 new_buf[offset]=']'; offset++; \
1006 if (recv_port_no!=SIP_PORT){ \
1007 new_buf[offset]=':'; offset++; \
1008 memcpy(new_buf+offset, \
1010 recv_port_str->len); \
1011 offset+=recv_port_str->len; \
1013 switch(msg->rcv.bind_address->proto){ \
1016 break; /* nothing to do, udp is default*/ \
1018 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1019 TRANSPORT_PARAM_LEN); \
1020 offset+=TRANSPORT_PARAM_LEN; \
1021 if (msg->rcv.proto == PROTO_WS) { \
1022 memcpy(new_buf+offset, "ws", 2); \
1025 memcpy(new_buf+offset, "tcp", 3); \
1030 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1031 TRANSPORT_PARAM_LEN); \
1032 offset+=TRANSPORT_PARAM_LEN; \
1033 if (msg->rcv.proto == PROTO_WS || msg->rcv.proto == PROTO_WSS) { \
1034 memcpy(new_buf+offset, "ws", 2); \
1037 memcpy(new_buf+offset, "tls", 3); \
1042 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1043 TRANSPORT_PARAM_LEN); \
1044 offset+=TRANSPORT_PARAM_LEN; \
1045 memcpy(new_buf+offset, "sctp", 4); \
1049 LM_CRIT("unknown proto %d\n", msg->rcv.bind_address->proto); \
1054 LM_CRIT("FIXME: null bind_address\n"); \
1057 case SUBST_SND_IP: \
1059 if ((send_sock->address.af!=AF_INET) && \
1060 (send_address_str->s[0]!='[')){\
1061 new_buf[offset]='['; offset++; \
1063 memcpy(new_buf+offset, send_address_str->s, \
1064 send_address_str->len); \
1065 offset+=send_address_str->len; \
1066 if ((send_sock->address.af!=AF_INET) && \
1067 (send_address_str->s[0]!='[')){\
1068 new_buf[offset]=']'; offset++; \
1072 LM_CRIT("FIXME: null send_sock\n"); \
1075 case SUBST_SND_PORT: \
1077 memcpy(new_buf+offset, send_port_str->s, \
1078 send_port_str->len); \
1079 offset+=send_port_str->len; \
1082 LM_CRIT("FIXME: null send_sock\n"); \
1085 case SUBST_SND_ALL: \
1088 if ((send_sock->address.af!=AF_INET) && \
1089 (send_address_str->s[0]!='[')){\
1090 new_buf[offset]='['; offset++; \
1092 memcpy(new_buf+offset, send_address_str->s, \
1093 send_address_str->len); \
1094 offset+=send_address_str->len; \
1095 if ((send_sock->address.af!=AF_INET) && \
1096 (send_address_str->s[0]!='[')){\
1097 new_buf[offset]=']'; offset++; \
1100 if ((send_sock->port_no!=SIP_PORT) || \
1101 (send_port_str!=&(send_sock->port_no_str))){ \
1102 new_buf[offset]=':'; offset++; \
1103 memcpy(new_buf+offset, send_port_str->s, \
1104 send_port_str->len); \
1105 offset+=send_port_str->len; \
1107 switch(send_sock->proto){ \
1110 break; /* nothing to do, udp is default*/ \
1112 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1113 TRANSPORT_PARAM_LEN); \
1114 offset+=TRANSPORT_PARAM_LEN; \
1115 if (send_info->proto == PROTO_WS) { \
1116 memcpy(new_buf+offset, "ws", 2); \
1119 memcpy(new_buf+offset, "tcp", 3); \
1124 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1125 TRANSPORT_PARAM_LEN); \
1126 offset+=TRANSPORT_PARAM_LEN; \
1127 if (send_info->proto == PROTO_WS || send_info->proto == PROTO_WSS) { \
1128 memcpy(new_buf+offset, "ws", 2); \
1131 memcpy(new_buf+offset, "tls", 3); \
1136 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1137 TRANSPORT_PARAM_LEN); \
1138 offset+=TRANSPORT_PARAM_LEN; \
1139 memcpy(new_buf+offset, "sctp", 4); \
1143 LM_CRIT("unknown proto %d\n", send_sock->proto); \
1145 SENDCOMP_PARAM_ADD \
1148 LM_CRIT("FIXME: null bind_address\n"); \
1151 case SUBST_RCV_PROTO: \
1152 if (msg->rcv.bind_address){ \
1153 switch(msg->rcv.bind_address->proto){ \
1156 memcpy(new_buf+offset, "udp", 3); \
1160 if (msg->rcv.proto == PROTO_WS) { \
1161 memcpy(new_buf+offset, "ws", 2); \
1164 memcpy(new_buf+offset, "tcp", 3); \
1169 if (msg->rcv.proto == PROTO_WS || msg->rcv.proto == PROTO_WSS) { \
1170 memcpy(new_buf+offset, "ws", 2); \
1173 memcpy(new_buf+offset, "tls", 3); \
1178 memcpy(new_buf+offset, "sctp", 4); \
1182 LM_CRIT("unknown proto %d\n", msg->rcv.bind_address->proto); \
1186 LM_CRIT("FIXME: null send_sock \n"); \
1189 case SUBST_SND_PROTO: \
1191 switch(send_sock->proto){ \
1194 memcpy(new_buf+offset, "udp", 3); \
1198 if (send_info->proto == PROTO_WS) { \
1199 memcpy(new_buf+offset, "ws", 2); \
1202 memcpy(new_buf+offset, "tcp", 3); \
1207 if (send_info->proto == PROTO_WS || send_info->proto == PROTO_WSS) { \
1208 memcpy(new_buf+offset, "ws", 2); \
1211 memcpy(new_buf+offset, "tls", 3); \
1216 memcpy(new_buf+offset, "sctp", 4); \
1220 LM_CRIT("unknown proto %d\n", send_sock->proto); \
1224 LM_CRIT("FIXME: null send_sock \n"); \
1228 LM_CRIT("unknown subst type %d\n", (subst_l)->u.subst); \
1232 send_sock=send_info->send_sock;
1236 /* init send_address_str & send_port_str */
1237 if (msg->set_global_address.len)
1238 send_address_str=&(msg->set_global_address);
1240 send_address_str=&(send_sock->address_str);
1241 if (msg->set_global_port.len)
1242 send_port_str=&(msg->set_global_port);
1244 send_port_str=&(send_sock->port_no_str);
1245 /* init send_address_str & send_port_str */
1246 if(send_sock && send_sock->useinfo.name.len>0)
1247 send_address_str=&(send_sock->useinfo.name);
1248 else if (msg->set_global_address.len)
1249 send_address_str=&(msg->set_global_address);
1251 send_address_str=&(send_sock->address_str);
1252 if(send_sock && send_sock->useinfo.port_no>0)
1253 send_port_str=&(send_sock->useinfo.port_no_str);
1254 else if (msg->set_global_port.len)
1255 send_port_str=&(msg->set_global_port);
1257 send_port_str=&(send_sock->port_no_str);
1258 /* init recv_address_str, recv_port_str & recv_port_no */
1259 if(msg->rcv.bind_address) {
1260 if(msg->rcv.bind_address->useinfo.name.len>0)
1261 recv_address_str=&(msg->rcv.bind_address->useinfo.name);
1263 recv_address_str=&(msg->rcv.bind_address->address_str);
1264 if(msg->rcv.bind_address->useinfo.port_no>0) {
1265 recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
1266 recv_port_no = msg->rcv.bind_address->useinfo.port_no;
1268 recv_port_str=&(msg->rcv.bind_address->port_no_str);
1269 recv_port_no = msg->rcv.bind_address->port_no;
1274 offset=*new_buf_offs;
1275 s_offset=*orig_offs;
1277 for (t=lumps;t;t=t->next){
1280 case LUMP_ADD_SUBST:
1282 /* skip if this is an OPT lump and the condition is
1284 if ((t->op==LUMP_ADD_OPT) &&
1285 (!lump_check_opt(t, msg, send_info)))
1287 /* just add it here! */
1288 /* process before */
1289 for(r=t->before;r;r=r->before){
1292 /*just add it here*/
1293 memcpy(new_buf+offset, r->u.value, r->len);
1296 case LUMP_ADD_SUBST:
1300 /* skip if this is an OPT lump and the condition is
1302 if (!lump_check_opt(r, msg, send_info))
1306 /* only ADD allowed for before/after */
1307 LM_CRIT("invalid op for data lump (%x)\n", r->op);
1311 /* copy "main" part */
1314 memcpy(new_buf+offset, t->u.value, t->len);
1317 case LUMP_ADD_SUBST:
1321 /* do nothing, it's only a condition */
1324 /* should not ever get here */
1325 LM_CRIT("unhandled data lump op %d\n", t->op);
1328 for(r=t->after;r;r=r->after){
1331 /*just add it here*/
1332 memcpy(new_buf+offset, r->u.value, r->len);
1335 case LUMP_ADD_SUBST:
1339 /* skip if this is an OPT lump and the condition is
1341 if (!lump_check_opt(r, msg, send_info))
1345 /* only ADD allowed for before/after */
1346 LM_CRIT("invalid op for data lump (%x)\n", r->op);
1353 /* copy till offset */
1354 if (s_offset>t->u.offset){
1355 LM_DBG("WARNING: (%d) overlapped lumps offsets,"
1356 " ignoring(%x, %x)\n", t->op, s_offset,t->u.offset);
1357 /* this should've been fixed above (when computing len) */
1361 size=t->u.offset-s_offset;
1362 if (size > 0 && flag == FLAG_MSG_ALL){
1363 memcpy(new_buf+offset, orig+s_offset,size);
1366 } else if (flag == FLAG_MSG_LUMPS_ONLY) {
1367 /* do not copy the whole message, jump to the lumps offs */
1371 /* the LUMP_DELs are printed with "- " before them */
1372 if (t->op==LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) {
1373 new_buf[offset++] = '-';
1374 new_buf[offset++] = ' ';
1377 /* process before */
1378 for(r=t->before;r;r=r->before){
1381 /*just add it here*/
1382 memcpy(new_buf+offset, r->u.value, r->len);
1385 case LUMP_ADD_SUBST:
1389 /* skip if this is an OPT lump and the condition is
1391 if (!lump_check_opt(r, msg, send_info))
1392 goto skip_nop_before;
1395 /* only ADD allowed for before/after */
1396 LM_CRIT("invalid op for data lump (%x)\n",r->op);
1400 /* process main (del only) */
1401 if (t->op==LUMP_DEL && flag == FLAG_MSG_ALL){
1402 /* skip len bytes from orig msg */
1404 } else if (t->op==LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) {
1405 /* copy lump value and indent as necessarely */
1406 memcpy(new_buf+offset, orig + t->u.offset, t->len);
1408 if (new_buf[offset-1] != '\n') {
1409 new_buf[offset] = '\n';
1412 /* skip len bytes from orig msg */
1417 for(r=t->after;r;r=r->after){
1420 /*just add it here*/
1421 memcpy(new_buf+offset, r->u.value, r->len);
1424 case LUMP_ADD_SUBST:
1428 /* skip if this is an OPT lump and the condition is
1430 if (!lump_check_opt(r, msg, send_info))
1431 goto skip_nop_after;
1434 /* only ADD allowed for before/after */
1435 LM_CRIT("invalid op for data lump (%x)\n", r->op);
1441 LM_CRIT("unknown op (%x)\n", t->op);
1444 *new_buf_offs=offset;
1445 *orig_offs=s_offset;
1447 /* add '\0' to char* lump list to print it smoothly */
1448 if (flag == FLAG_MSG_LUMPS_ONLY) {
1449 new_buf[offset] = '\0';
1451 #undef RCVCOMP_PARAM_ADD
1452 #undef SENDCOMP_PARAM_ADD
1457 * Adjust/insert Content-Length if necessary
1459 static inline int adjust_clen(struct sip_msg* msg, int body_delta, int proto)
1461 struct lump* anchor;
1463 int clen_len, body_only;
1467 #endif /* USE_TCP */
1469 /* Calculate message length difference caused by lumps modifying message
1470 * body, from this point on the message body must not be modified. Zero
1471 * value indicates that the body hasn't been modified
1478 /* check to see if we need to add clen */
1480 if (proto == PROTO_TCP
1482 || proto == PROTO_TLS
1485 if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1){
1486 LM_ERR("error parsing content-length\n");
1489 if (unlikely(msg->content_length==0)){
1490 /* not present, we need to add it */
1491 /* msg->unparsed should point just before the final crlf
1492 * - whole message was parsed by the above parse_headers
1493 * which did not find content-length */
1494 anchor=anchor_lump(msg, msg->unparsed-msg->buf, 0,
1495 HDR_CONTENTLENGTH_T);
1497 LM_ERR("cannot set clen anchor\n");
1502 /* compute current content length and compare it with the
1503 one in the message */
1505 if (unlikely(body==0)){
1506 ser_error=E_BAD_REQ;
1507 LM_ERR("no message body found (missing crlf?)");
1510 comp_clen=msg->len-(int)(body-msg->buf)+body_delta;
1511 if (comp_clen!=(int)(long)msg->content_length->parsed){
1512 /* note: we don't distinguish here between received with
1513 wrong content-length and content-length changed, we just
1514 fix it automatically in both cases (the reason being
1515 that an error message telling we have received a msg-
1516 with wrong content-length is of very little use) */
1517 anchor = del_lump(msg, msg->content_length->body.s-msg->buf,
1518 msg->content_length->body.len,
1519 HDR_CONTENTLENGTH_T);
1521 LM_ERR("Can't remove original Content-Length\n");
1528 #endif /* USE_TCP */
1530 if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) {
1531 LM_ERR("Error parsing Content-Length\n");
1535 /* The body has been changed, try to find
1536 * existing Content-Length
1538 /* no need for Content-Length if it's and UDP packet and
1539 * it hasn't Content-Length already */
1540 if (msg->content_length==0){
1541 /* content-length doesn't exist, append it */
1542 /* msg->unparsed should point just before the final crlf
1543 * - whole message was parsed by the above parse_headers
1544 * which did not find content-length */
1545 if (proto!=PROTO_UDP){
1546 anchor=anchor_lump(msg, msg->unparsed-msg->buf, 0,
1547 HDR_CONTENTLENGTH_T);
1549 LM_ERR("cannot set clen anchor\n");
1554 LM_DBG("UDP packet with no clen => not adding one \n"); */
1556 /* Content-Length has been found, remove it */
1557 anchor = del_lump( msg, msg->content_length->body.s - msg->buf,
1558 msg->content_length->body.len,
1559 HDR_CONTENTLENGTH_T);
1561 LM_ERR("Can't remove original Content-Length\n");
1568 clen_buf = clen_builder(msg, &clen_len, body_delta, body_only);
1569 if (!clen_buf) goto error;
1570 if (insert_new_lump_after(anchor, clen_buf, clen_len,
1571 HDR_CONTENTLENGTH_T) == 0)
1577 if (clen_buf) pkg_free(clen_buf);
1581 static inline int find_line_start(char *text, unsigned int text_len,
1582 char **buf, unsigned int *buf_len)
1590 while (text_len <= len) {
1591 if (strncmp(text, start, text_len) == 0) {
1596 if ((ch = memchr(start, 13, len - 1))) {
1597 if (*(ch + 1) != 10) {
1598 LM_ERR("No LF after CR\n");
1601 len = len - (ch - start + 2);
1604 LM_ERR("No CRLF found\n");
1611 static inline int get_line(str s)
1615 if ((ch = memchr(s.s, 13, s.len))) {
1616 if (*(ch + 1) != 10) {
1617 LM_ERR("No LF after CR\n");
1620 return ch - s.s + 2;
1622 LM_ERR("No CRLF found\n");
1628 int replace_body(struct sip_msg *msg, str txt)
1630 struct lump *anchor;
1634 body.s = get_body(msg);
1637 LM_ERR("malformed sip message\n");
1640 body.len = msg->len -(int)(body.s-msg->buf);
1641 LM_DBG("old size body[%d] actual[%d]\n", body.len, txt.len);
1642 if(body.s+body.len>msg->buf+msg->len)
1644 LM_ERR("invalid content length: %d\n", body.len);
1647 del_nonshm_lump( &(msg->body_lumps) );
1648 msg->body_lumps = NULL;
1650 if(del_lump(msg, body.s-msg->buf, body.len, 0) == 0)
1652 LM_ERR("cannot delete existing body");
1656 anchor = anchor_lump(msg, body.s - msg->buf, 0, 0);
1659 LM_ERR("failed to get anchor\n");
1663 buf=pkg_malloc(sizeof(char)*txt.len);
1669 memcpy(buf, txt.s, txt.len);
1670 if(insert_new_lump_after(anchor, buf, txt.len, 0)==0)
1672 LM_ERR("failed to insert body lump\n");
1680 * returns the boundary defined by the Content-Type
1683 int get_boundary(struct sip_msg* msg, str* boundary)
1687 param_hooks_t hooks;
1689 params.s = memchr(msg->content_type->body.s, ';',
1690 msg->content_type->body.len);
1691 if (params.s == NULL)
1693 LM_INFO("Content-Type hdr has no params <%.*s>\n",
1694 msg->content_type->body.len, msg->content_type->body.s);
1697 params.len = msg->content_type->body.len -
1698 (params.s - msg->content_type->body.s);
1699 if (parse_params(¶ms, CLASS_ANY, &hooks, &list) < 0)
1701 LM_ERR("while parsing Content-Type params\n");
1706 for (p = list; p; p = p->next) {
1707 if ((p->name.len == 8)
1708 && (strncasecmp(p->name.s, "boundary", 8) == 0))
1710 boundary->s = pkg_malloc(p->body.len + 2);
1711 if (boundary->s == NULL)
1714 LM_ERR("no memory for boundary string\n");
1717 *(boundary->s) = '-';
1718 *(boundary->s + 1) = '-';
1719 memcpy(boundary->s + 2, p->body.s, p->body.len);
1720 boundary->len = 2 + p->body.len;
1721 LM_DBG("boundary is <%.*s>\n", boundary->len, boundary->s);
1729 int check_boundaries(struct sip_msg *msg, struct dest_info *send_info)
1734 str bsuffix = {"\r\n", 2};
1735 str fsuffix = {"--\r\n", 4};
1739 struct str_list* lb = NULL;
1740 struct str_list* lb_t = NULL;
1742 int t, ret, lb_size;
1745 if(!(msg->msg_flags&FL_BODY_MULTIPART)) return 0;
1748 buf.s = build_body(msg, (unsigned int *)&buf.len, &ret, send_info);
1750 LM_ERR("Can't get body\n");
1754 t = tmp.len = buf.len;
1755 if(get_boundary(msg, &ob)!=0) {
1756 if(tmp.s) pkg_free(tmp.s);
1759 if(str_append(&ob, &bsuffix, &b)!=0) {
1760 LM_ERR("Can't append suffix to boundary\n");
1763 if(str_append(&ob, &fsuffix,&fb)!=0) {
1764 LM_ERR("Can't append suffix to final boundary\n");
1770 if(find_line_start(b.s, ret, &tmp.s,
1771 (unsigned int *)&tmp.len))
1773 /*LM_DBG("found t[%d] tmp.len[%d]:[%.*s]\n",
1774 t, tmp.len, tmp.len, tmp.s);*/
1777 lb = pkg_malloc(sizeof(struct str_list));
1783 lb->s.len = tmp.len;
1789 lb_t = append_str_list(tmp.s, tmp.len, &lb_t, &lb_size);
1791 lb_found = lb_found + 1;
1792 tmp.s = tmp.s + ret;
1794 tmp.len = tmp.len - ret;
1800 LM_ERR("found[%d] wrong number of boundaries\n", lb_found);
1803 /* adding 2 chars in advance */
1804 body.len = buf.len + 2;
1805 body.s = pkg_malloc(sizeof(char)*body.len);
1810 pb = body.s; body.len = 0;
1814 tmp.s = lb_t->s.s; tmp.len = lb_t->s.len;
1815 tmp.len = get_line(lb_t->s);
1816 if(tmp.len!=b.len || strncmp(b.s, tmp.s, b.len)!=0)
1818 LM_DBG("malformed bondary in the middle\n");
1819 memcpy(pb, b.s, b.len); body.len = body.len + b.len;
1821 t = lb_t->s.s - (lb_t->s.s + tmp.len);
1822 memcpy(pb, lb_t->s.s+tmp.len, t); pb = pb + t;
1823 /*LM_DBG("new chunk[%d][%.*s]\n", t, t, pb-t);*/
1826 t = lb_t->next->s.s - lb_t->s.s;
1827 memcpy(pb, lb_t->s.s, t);
1828 /*LM_DBG("copy[%d][%.*s]\n", t, t, pb);*/
1831 body.len = body.len + t;
1832 /*LM_DBG("body[%d][%.*s]\n", body.len, body.len, body.s);*/
1834 if(!lb_t->next) lb_t = NULL;
1837 tmp.s = lb->s.s; tmp.len = lb->s.len;
1838 tmp.len = get_line(lb->s);
1839 if(tmp.len!=fb.len || strncmp(fb.s, tmp.s, fb.len)!=0)
1841 LM_DBG("last bondary without -- at the end\n");
1842 memcpy(pb, fb.s, fb.len);
1843 /*LM_DBG("new chunk[%d][%.*s]\n", fb.len, fb.len, pb);*/
1845 body.len = body.len + fb.len;
1848 memcpy(pb, lb->s.s, lb->s.len); pb = pb + lb->s.len;
1849 body.len = body.len + lb->s.len;
1850 /*LM_DBG("copy[%d][%.*s]\n", lb->s.len, lb->s.len, pb - lb->s.len);*/
1852 /*LM_DBG("body[%d][%.*s] expected[%ld]\n",
1853 body.len, body.len, body.s, pb-body.s); */
1854 if(!replace_body(msg, body))
1856 LM_ERR("Can't replace body\n");
1859 msg->msg_flags &= ~FL_BODY_MULTIPART;
1867 if(ob.s) pkg_free(ob.s);
1868 if(b.s) pkg_free(b.s);
1869 if(fb.s) pkg_free(fb.s);
1870 if(body.s) pkg_free(body.s);
1871 if(buf.s) pkg_free(buf.s);
1881 /** builds a request in memory from another sip request.
1883 * Side-effects: - it adds lumps to the msg which are _not_ cleaned.
1884 * The added lumps are HDR_VIA_T (almost always added), HDR_CONTENLENGTH_T
1885 * and HDR_ROUTE_T (when a Route: header is added as a result of a non-null
1887 * - it might change send_info->proto and send_info->send_socket
1888 * if proto fallback is enabled (see below).
1890 * Uses also global_req_flags ( OR'ed with msg->msg_flags, see send_info
1893 * @param msg - sip message structure, complete with lumps
1894 * @param returned_len - result length (filled in)
1895 * @param send_info - dest_info structure (value/result), contains where the
1896 * packet will be sent to (it's needed for building a
1897 * correct via, fill RR lumps a.s.o.). If MTU based
1898 * protocol fall-back is enabled (see flags below),
1899 * send_info->proto might be updated with the new
1901 * msg->msg_flags used:
1902 * - FL_TCP_MTU_FB, FL_TLS_MTU_FB and FL_SCTP_MTU_FB -
1903 * fallback to the corresp. proto if the built
1904 * message > mtu and send_info->proto==PROTO_UDP.
1905 * It will also update send_info->proto.
1906 * - FL_FORCE_RPORT: add rport to via
1907 * @param mode - flags for building the message, can be a combination of:
1908 * * BUILD_NO_LOCAL_VIA - don't add a local via
1909 * * BUILD_NO_VIA1_UPDATE - don't update first via (rport,
1911 * * BUILD_NO_PATH - don't add a Route: header with the
1912 * msg->path_vec content.
1913 * * BUILD_IN_SHM - build the result in shm memory
1915 * @return pointer to the new request (pkg_malloc'ed or shm_malloc'ed,
1916 * depending on the presence of the BUILD_IN_SHM flag, needs freeing when
1917 * done) and sets returned_len or 0 on error.
1919 char * build_req_buf_from_sip_req( struct sip_msg* msg,
1920 unsigned int *returned_len,
1921 struct dest_info* send_info,
1924 unsigned int len, new_len, received_len, rport_len, uri_len, via_len,
1932 unsigned int offset, s_offset, size;
1933 struct lump* via_anchor;
1934 struct lump* via_lump;
1935 struct lump* via_insert_param;
1936 struct lump* path_anchor;
1937 struct lump* path_lump;
1940 unsigned int udp_mtu;
1941 struct dest_info di;
1958 flags=msg->msg_flags|global_req_flags;
1959 if(check_boundaries(msg, send_info)<0){
1960 LM_WARN("check_boundaries error\n");
1962 /* Calculate message body difference and adjust Content-Length */
1963 body_delta = lumps_len(msg, msg->body_lumps, send_info);
1964 if (adjust_clen(msg, body_delta, send_info->proto) < 0) {
1965 LM_ERR("Error while adjusting Content-Length\n");
1969 if(unlikely(mode&BUILD_NO_LOCAL_VIA))
1970 goto after_local_via;
1972 /* create the via header */
1973 branch.s=msg->add_to_branch_s;
1974 branch.len=msg->add_to_branch_len;
1976 via_anchor=anchor_lump(msg, msg->via1->hdr.s-buf, 0, HDR_VIA_T);
1977 if (unlikely(via_anchor==0)) goto error00;
1978 line_buf = create_via_hf( &via_len, msg, send_info, &branch);
1979 if (unlikely(!line_buf)){
1980 LM_ERR("could not create Via header\n");
1984 if(unlikely(mode&BUILD_NO_VIA1_UPDATE))
1985 goto after_update_via1;
1986 /* check if received needs to be added */
1987 if ( received_test(msg) ) {
1988 if ((received_buf=received_builder(msg,&received_len))==0){
1989 LM_ERR("received_builder failed\n");
1990 goto error00; /* free also line_buf */
1994 /* check if rport needs to be updated:
1995 * - if FL_FORCE_RPORT is set add it (and del. any previous version)
1996 * - if via already contains an rport add it and overwrite the previous
1997 * rport value if present (if you don't want to overwrite the previous
1998 * version remove the comments) */
1999 if ((flags&FL_FORCE_RPORT)||
2000 (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)){
2001 if ((rport_buf=rport_builder(msg, &rport_len))==0){
2002 LM_ERR("rport_builder failed\n");
2003 goto error00; /* free everything */
2007 /* find out where the offset of the first parameter that should be added
2008 * (after host:port), needed by add receive & maybe rport */
2009 if (msg->via1->params.s){
2010 size= msg->via1->params.s-msg->via1->hdr.s-1; /*compensate
2013 size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
2014 if (msg->via1->port!=0){
2015 /*size+=strlen(msg->via1->hdr.s+size+1)+1;*/
2016 size += msg->via1->port_str.len + 1; /* +1 for ':'*/
2019 /* no longer necessary, now hots.s contains [] */
2020 if(send_sock->address.af==AF_INET6) size+=1; /* +1 for ']'*/
2023 /* if received needs to be added, add anchor after host and add it, or
2024 * overwrite the previous one if already present */
2026 if (msg->via1->received){ /* received already present => overwrite it*/
2027 via_insert_param=del_lump(msg,
2028 msg->via1->received->start-buf-1, /*;*/
2029 msg->via1->received->size+1, /*;*/ HDR_VIA_T);
2030 }else if (via_insert_param==0){ /* receive not present, ok */
2031 via_insert_param=anchor_lump(msg, msg->via1->hdr.s-buf+size, 0,
2034 if (via_insert_param==0) goto error00; /* free received_buf */
2035 if (insert_new_lump_after(via_insert_param, received_buf, received_len,
2037 goto error00; /* free received_buf */
2039 received_buf = NULL;
2041 /* if rport needs to be updated, delete it if present and add it's value */
2043 if (msg->via1->rport){ /* rport already present */
2044 via_insert_param=del_lump(msg,
2045 msg->via1->rport->start-buf-1, /*';'*/
2046 msg->via1->rport->size+1 /* ; */, HDR_VIA_T);
2047 }else if (via_insert_param==0){ /*force rport, no rport present */
2048 /* no rport, add it */
2049 via_insert_param=anchor_lump(msg, msg->via1->hdr.s-buf+size, 0,
2052 if (via_insert_param==0) goto error00; /* free rport_buf */
2053 if (insert_new_lump_after(via_insert_param, rport_buf, rport_len,
2055 goto error00; /* free rport_buf */
2061 /* add route with path content */
2062 if(unlikely(!(mode&BUILD_NO_PATH) && msg->path_vec.s &&
2063 msg->path_vec.len)){
2064 path_buf.len=ROUTE_PREFIX_LEN+msg->path_vec.len+CRLF_LEN;
2065 path_buf.s=pkg_malloc(path_buf.len+1);
2066 if (unlikely(path_buf.s==0)){
2067 LM_ERR("out of memory\n");
2068 ser_error=E_OUT_OF_MEM;
2071 memcpy(path_buf.s, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
2072 memcpy(path_buf.s+ROUTE_PREFIX_LEN, msg->path_vec.s,
2074 memcpy(path_buf.s+ROUTE_PREFIX_LEN+msg->path_vec.len, CRLF, CRLF_LEN);
2075 path_buf.s[path_buf.len]=0;
2076 /* insert Route header either before the other routes
2077 (if present & parsed), after the local via or after in front of
2078 the first via if we don't add a local via*/
2080 path_anchor=anchor_lump(msg, msg->route->name.s-buf, 0,
2082 }else if (likely(via_anchor)){
2083 path_anchor=via_anchor;
2084 }else if (likely(msg->via1)){
2085 path_anchor=anchor_lump(msg, msg->via1->hdr.s-buf, 0,
2088 /* if no via1 (theoretically possible for non-sip messages,
2089 e.g. http xmlrpc) */
2090 path_anchor=anchor_lump(msg, msg->headers->name.s-buf, 0,
2093 if (unlikely(path_anchor==0))
2095 if (unlikely((path_lump=insert_new_lump_after(path_anchor, path_buf.s,
2096 path_buf.len, HDR_ROUTE_T))==0)) {
2101 /* compute new msg len and fix overlapping zones*/
2102 new_len=len+body_delta+lumps_len(msg, msg->add_rm, send_info)+via_len;
2104 LM_ERR("new_len(%d)=len(%d)+lumps_len\n", new_len, len);
2106 udp_mtu=cfg_get(core, core_cfg, udp_mtu);
2107 di.proto=PROTO_NONE;
2108 if (unlikely((send_info->proto==PROTO_UDP) && udp_mtu &&
2109 (flags & FL_MTU_FB_MASK) && (new_len>udp_mtu)
2110 && (!(mode&BUILD_NO_LOCAL_VIA)))){
2112 di=*send_info; /* copy whole struct - will be used in the Via builder */
2113 di.proto=PROTO_NONE; /* except the proto */
2115 if (!tcp_disable && (flags & FL_MTU_TCP_FB) &&
2116 (di.send_sock=get_send_socket(msg, &send_info->to, PROTO_TCP))){
2120 else if (!tls_disable && (flags & FL_MTU_TLS_FB) &&
2121 (di.send_sock=get_send_socket(msg, &send_info->to, PROTO_TLS))){
2124 #endif /* USE_TLS */
2125 #endif /* USE_TCP */
2129 #endif /* USE_TCP */
2130 if (!sctp_disable && (flags & FL_MTU_SCTP_FB) &&
2131 (di.send_sock=get_send_socket(msg, &send_info->to, PROTO_SCTP))){
2132 di.proto=PROTO_SCTP;
2134 #endif /* USE_SCTP */
2136 if (di.proto!=PROTO_NONE){
2138 if(likely(line_buf)) pkg_free(line_buf);
2139 line_buf = create_via_hf( &via_len, msg, &di, &branch);
2141 LM_ERR("memory allocation failure!\n");
2147 /* add via header to the list */
2148 /* try to add it before msg. 1st via */
2149 /* add first via, as an anchor for second via*/
2150 if(likely(line_buf)) {
2151 if ((via_lump=insert_new_lump_before(via_anchor, line_buf, via_len,
2157 if (msg->new_uri.s){
2158 uri_len=msg->new_uri.len;
2159 new_len=new_len-msg->first_line.u.request.uri.len+uri_len;
2161 if(unlikely(mode&BUILD_IN_SHM))
2162 new_buf=(char*)shm_malloc(new_len+1);
2164 new_buf=(char*)pkg_malloc(new_len+1);
2166 ser_error=E_OUT_OF_MEM;
2167 LM_ERR("out of memory\n");
2172 if (msg->new_uri.s){
2173 /* copy message up to uri */
2174 size=msg->first_line.u.request.uri.s-buf;
2175 memcpy(new_buf, buf, size);
2179 memcpy(new_buf+offset, msg->new_uri.s, uri_len);
2181 s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */
2184 /* copy msg adding/removing lumps */
2185 process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, FLAG_MSG_ALL);
2186 process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset,send_info, FLAG_MSG_ALL);
2187 /* copy the rest of the message */
2188 memcpy(new_buf+offset, buf+s_offset, len-s_offset);
2191 /* update the send_info if udp_mtu affected */
2192 if (di.proto!=PROTO_NONE) {
2193 send_info->proto=di.proto;
2194 send_info->send_sock=di.send_sock;
2198 if (new_buf[new_len-1]==0) {
2199 LM_ERR("0 in the end\n");
2204 *returned_len=new_len;
2208 if (received_buf) pkg_free(received_buf);
2209 if (rport_buf) pkg_free(rport_buf);
2210 if (path_buf.s) pkg_free(path_buf.s);
2211 if (line_buf) pkg_free(line_buf);
2217 char * generate_res_buf_from_sip_res( struct sip_msg* msg,
2218 unsigned int *returned_len, unsigned int mode)
2220 unsigned int new_len, via_len, body_delta;
2222 unsigned offset, s_offset, via_offset;
2230 if(unlikely(mode&BUILD_NO_VIA1_UPDATE)) {
2234 /* we must remove the first via */
2235 if (msg->via1->next) {
2236 via_len=msg->via1->bsize;
2237 via_offset=msg->h_via1->body.s-buf;
2239 via_len=msg->h_via1->len;
2240 via_offset=msg->h_via1->name.s-buf;
2244 /* Calculate message body difference and adjust
2247 body_delta = lumps_len(msg, msg->body_lumps, 0);
2248 if (adjust_clen(msg, body_delta, (msg->via2? msg->via2->proto:PROTO_UDP))
2250 LM_ERR("error while adjusting Content-Length\n");
2254 if(likely(!(mode&BUILD_NO_VIA1_UPDATE))) {
2255 /* remove the first via*/
2256 if (del_lump( msg, via_offset, via_len, HDR_VIA_T)==0){
2257 LM_ERR("error trying to remove first via\n");
2262 new_len=len+body_delta+lumps_len(msg, msg->add_rm, 0); /*FIXME: we don't
2263 know the send sock */
2265 LM_DBG("old size: %d, new size: %d\n", len, new_len);
2266 new_buf=(char*)pkg_malloc(new_len+1); /* +1 is for debugging
2269 LM_ERR("out of mem\n");
2272 new_buf[new_len]=0; /* debug: print the message */
2274 /*FIXME: no send sock*/
2275 process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, 0, FLAG_MSG_ALL);/*FIXME:*/
2276 process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, 0, FLAG_MSG_ALL);
2277 /* copy the rest of the message */
2278 memcpy(new_buf+offset,
2282 LM_DBG("copied size: orig:%d, new: %d, rest: %d msg=\n%s\n",
2283 s_offset, offset, len-s_offset, new_buf);
2285 *returned_len=new_len;
2292 char * build_res_buf_from_sip_res( struct sip_msg* msg,
2293 unsigned int *returned_len)
2295 return generate_res_buf_from_sip_res(msg, returned_len, 0);
2298 char * build_res_buf_from_sip_req( unsigned int code, str *text ,str *new_tag,
2299 struct sip_msg* msg, unsigned int *returned_len, struct bookmark *bmark)
2302 unsigned int len,foo;
2303 struct hdr_field *hdr;
2304 struct lump_rpl *lump;
2305 struct lump_rpl *body;
2308 unsigned int received_len;
2310 unsigned int rport_len;
2312 unsigned int warning_len;
2313 char* content_len_buf;
2314 unsigned int content_len_len;
2323 received_buf=rport_buf=warning_buf=content_len_buf=0;
2324 received_len=rport_len=warning_len=content_len_len=0;
2326 to_tag.s=0; /* fixes gcc 4.0 warning */
2329 /* force parsing all headers -- we want to return all
2330 Via's in the reply and they may be scattered down to the
2331 end of header (non-block Vias are a really poor property
2333 if (parse_headers( msg, HDR_EOH_F, 0 )==-1) {
2334 LM_ERR("alas, parse_headers failed\n");
2338 /*computes the length of the new response buffer*/
2341 httpreq = IS_HTTP(msg);
2343 /* check if received needs to be added */
2344 if (received_test(msg)) {
2345 if ((received_buf=received_builder(msg,&received_len))==0) {
2346 LM_ERR("alas, received_builder failed\n");
2350 /* check if rport needs to be updated */
2351 if ( ((msg->msg_flags|global_req_flags)&FL_FORCE_RPORT)||
2352 (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)){
2353 if ((rport_buf=rport_builder(msg, &rport_len))==0){
2354 LM_ERR("rport_builder failed\n");
2355 goto error01; /* free everything */
2357 if (msg->via1->rport)
2358 len -= msg->via1->rport->size+1; /* include ';' */
2362 len += msg->first_line.u.request.version.len + 1/*space*/ + 3/*code*/ + 1/*space*/ +
2363 text->len + CRLF_LEN/*new line*/;
2364 /*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/
2365 for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) {
2366 switch (hdr->type) {
2368 if (new_tag && new_tag->len) {
2369 to_tag=get_to(msg)->tag_value;
2370 if ( to_tag.len || to_tag.s )
2371 len+=new_tag->len-to_tag.len;
2373 len+=new_tag->len+TOTAG_TOKEN_LEN/*";tag="*/;
2378 /* we always add CRLF to via*/
2379 len+=(hdr->body.s+hdr->body.len)-hdr->name.s+CRLF_LEN;
2380 if (hdr==msg->h_via1) len += received_len+rport_len;
2382 case HDR_RECORDROUTE_T:
2383 /* RR only for 1xx and 2xx replies */
2384 if (code<180 || code>=300)
2389 /* we keep the original termination for these headers*/
2393 /* do nothing, we are interested only in the above headers */
2398 for(lump=msg->reply_lump;lump;lump=lump->next) {
2399 len += lump->text.len;
2400 if (lump->flags&LUMP_RPL_BODY)
2404 if (server_signature && server_hdr.len)
2405 len += server_hdr.len + CRLF_LEN;
2408 warning_buf = warning_builder(msg,&warning_len);
2409 if (warning_buf) len += warning_len + CRLF_LEN;
2410 else LM_WARN("warning skipped -- too big\n");
2412 /* content length hdr */
2414 content_len_buf = int2str(body->text.len, (int*)&content_len_len);
2415 len += CONTENT_LENGTH_LEN + content_len_len + CRLF_LEN;
2417 len += CONTENT_LENGTH_LEN + 1/*0*/ + CRLF_LEN;
2419 /* end of message */
2420 len += CRLF_LEN; /*new line*/
2423 buf = (char*) pkg_malloc( len+1 );
2426 LM_ERR("out of memory; needs %d\n",len);
2430 /* filling the buffer*/
2433 memcpy( p , msg->first_line.u.request.version.s ,
2434 msg->first_line.u.request.version.len);
2435 p += msg->first_line.u.request.version.len;
2438 for ( i=2 , foo = code ; i>=0 ; i-- , foo=foo/10 )
2439 *(p+i) = '0' + foo - ( foo/10 )*10;
2442 memcpy( p , text->s , text->len );
2444 memcpy( p, CRLF, CRLF_LEN );
2447 for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) {
2451 /* if is HTTP, backup start of Via header in response */
2452 if(unlikely(httpreq)) pvia = p;
2453 if (hdr==msg->h_via1){
2455 if (msg->via1->rport){ /* delete the old one */
2456 /* copy until rport */
2457 append_str_trans( p, hdr->name.s ,
2458 msg->via1->rport->start-hdr->name.s-1,msg);
2459 /* copy new rport */
2460 append_str(p, rport_buf, rport_len);
2461 /* copy the rest of the via */
2462 append_str_trans(p, msg->via1->rport->start+
2463 msg->via1->rport->size,
2464 hdr->body.s+hdr->body.len-
2465 msg->via1->rport->start-
2466 msg->via1->rport->size, msg);
2467 }else{ /* just append the new one */
2468 /* normal whole via copy */
2469 append_str_trans( p, hdr->name.s ,
2470 (hdr->body.s+hdr->body.len)-hdr->name.s, msg);
2471 append_str(p, rport_buf, rport_len);
2474 /* normal whole via copy */
2475 append_str_trans( p, hdr->name.s ,
2476 (hdr->body.s+hdr->body.len)-hdr->name.s, msg);
2479 append_str( p, received_buf, received_len);
2481 /* normal whole via copy */
2482 append_str_trans( p, hdr->name.s,
2483 (hdr->body.s+hdr->body.len)-hdr->name.s, msg);
2485 append_str( p, CRLF,CRLF_LEN);
2486 /* if is HTTP, replace Via with Sia
2487 * - HTTP Via format is different than SIP Via
2489 if(unlikely(httpreq)) *pvia = 'S';
2491 case HDR_RECORDROUTE_T:
2492 /* RR only for 1xx and 2xx replies */
2493 if (code<180 || code>=300) break;
2494 append_str(p, hdr->name.s, hdr->len);
2497 if (new_tag && new_tag->len){
2498 if (to_tag.s ) { /* replacement */
2500 append_str( p, hdr->name.s, to_tag.s-hdr->name.s);
2501 /* to tag replacement */
2502 bmark->to_tag_val.s=p;
2503 bmark->to_tag_val.len=new_tag->len;
2504 append_str( p, new_tag->s,new_tag->len);
2505 /* the rest after to-tag */
2506 append_str( p, to_tag.s+to_tag.len,
2507 hdr->name.s+hdr->len-(to_tag.s+to_tag.len));
2508 }else{ /* adding a new to-tag */
2509 after_body=hdr->body.s+hdr->body.len;
2510 append_str( p, hdr->name.s, after_body-hdr->name.s);
2511 append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN);
2512 bmark->to_tag_val.s=p;
2513 bmark->to_tag_val.len=new_tag->len;
2514 append_str( p, new_tag->s,new_tag->len);
2515 append_str( p, after_body,
2516 hdr->name.s+hdr->len-after_body);
2519 } /* no new to-tag -- proceed to 1:1 copying */
2520 totags=((struct to_body*)(hdr->parsed))->tag_value.s;
2522 bmark->to_tag_val.s=p+(totags-hdr->name.s);
2523 bmark->to_tag_val.len=
2524 ((struct to_body*)(hdr->parsed))->tag_value.len;
2527 bmark->to_tag_val.len = 0;
2528 bmark->to_tag_val.s = p+(hdr->body.s+hdr->body.len-hdr->name.s);
2534 append_str(p, hdr->name.s, hdr->len);
2537 /* do nothing, we are interested only in the above headers */
2542 for(lump=msg->reply_lump;lump;lump=lump->next)
2543 if (lump->flags&LUMP_RPL_HDR){
2544 memcpy(p,lump->text.s,lump->text.len);
2545 p += lump->text.len;
2548 if (server_signature && server_hdr.len>0) {
2549 memcpy( p, server_hdr.s, server_hdr.len );
2551 memcpy( p, CRLF, CRLF_LEN );
2554 /* content_length hdr */
2555 if (content_len_len) {
2556 append_str( p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
2557 append_str( p, content_len_buf, content_len_len );
2558 append_str( p, CRLF, CRLF_LEN );
2560 append_str( p, CONTENT_LENGTH"0"CRLF,CONTENT_LENGTH_LEN+1+CRLF_LEN);
2562 /* warning header */
2564 memcpy( p, warning_buf, warning_len);
2566 memcpy( p, CRLF, CRLF_LEN);
2570 memcpy( p, CRLF, CRLF_LEN );
2574 memcpy ( p, body->text.s, body->text.len );
2579 LM_CRIT("diff len=%d p-buf=%d\n", len, (int)(p-buf));
2582 *returned_len = len;
2583 /* in req2reply, received_buf is not introduced to lumps and
2584 needs to be deleted here
2586 if (received_buf) pkg_free(received_buf);
2587 if (rport_buf) pkg_free(rport_buf);
2591 if (received_buf) pkg_free(received_buf);
2592 if (rport_buf) pkg_free(rport_buf);
2600 /* return number of chars printed or 0 if space exceeded;
2601 assumes buffer size of at least MAX_BRANCH_PARAM_LEN
2603 int branch_builder( unsigned int hash_index,
2604 /* only either parameter useful */
2605 unsigned int label, char * char_v,
2607 char *branch_str, int *len )
2613 /* hash id provided ... start with it */
2614 size=MAX_BRANCH_PARAM_LEN;
2618 memcpy(begin, MCOOKIE, MCOOKIE_LEN );
2619 size-=MCOOKIE_LEN;begin+=MCOOKIE_LEN;
2621 if (int2reverse_hex( &begin, &size, hash_index)==-1)
2625 *begin=BRANCH_SEPARATOR;
2629 /* string with request's characteristic value ... use it ... */
2631 if (memcpy(begin,char_v,MD5_LEN)) {
2632 begin+=MD5_LEN; size-=MD5_LEN;
2634 } else { /* ... use the "label" value otherwise */
2635 if (int2reverse_hex( &begin, &size, label )==-1)
2640 *begin=BRANCH_SEPARATOR;
2644 if (int2reverse_hex( &begin, &size, branch)==-1)
2647 *len=MAX_BRANCH_PARAM_LEN-size;
2654 /* uses only the send_info->send_socket, send_info->proto and
2655 * send_info->comp (so that a send_info used for sending can be passed
2656 * to this function w/o changes and the correct via will be built) */
2657 char* via_builder( unsigned int *len,
2658 struct dest_info* send_info /* where to send the reply */,
2659 str* branch, str* extra_params, struct hostport* hp)
2661 unsigned int via_len, extra_len;
2665 str* address_str; /* address displayed in via */
2666 str* port_str; /* port no displayed in via */
2667 struct socket_info* send_sock;
2668 int comp_len, comp_name_len;
2671 #endif /* USE_COMP */
2674 union sockaddr_union *from = NULL;
2675 union sockaddr_union local_addr;
2676 struct tcp_connection *con = NULL;
2678 send_sock=send_info->send_sock;
2679 /* use pre-set address in via, the outbound socket alias or address one */
2680 if (hp && hp->host->len)
2681 address_str=hp->host;
2682 else if(send_sock->useinfo.name.len>0)
2683 address_str=&(send_sock->useinfo.name);
2685 address_str=&(send_sock->address_str);
2686 if (hp && hp->port->len)
2688 else if(send_sock->useinfo.port_no>0)
2689 port_str=&(send_sock->useinfo.port_no_str);
2691 port_str=&(send_sock->port_no_str);
2693 comp_len=comp_name_len=0;
2696 switch(send_info->comp){
2700 comp_len=COMP_PARAM_LEN;
2701 comp_name_len=SIGCOMP_NAME_LEN;
2702 comp_name=SIGCOMP_NAME;
2705 comp_len=COMP_PARAM_LEN;
2706 comp_name_len=SERGZ_NAME_LEN;
2707 comp_name=SERGZ_NAME;
2710 LM_CRIT("unknown comp %d\n", send_info->comp);
2711 /* continue, we'll just ignore comp */
2713 #endif /* USE_COMP */
2715 via_prefix_len=MY_VIA_LEN+(send_info->proto==PROTO_SCTP);
2716 max_len=via_prefix_len +address_str->len /* space in MY_VIA */
2717 +2 /* just in case it is a v6 address ... [ ] */
2718 +1 /*':'*/+port_str->len
2719 +(branch?(MY_BRANCH_LEN+branch->len):0)
2720 +(extra_params?extra_params->len:0)
2721 +comp_len+comp_name_len
2723 line_buf=pkg_malloc( max_len );
2725 ser_error=E_OUT_OF_MEM;
2726 LM_ERR("out of memory\n");
2732 via_len=via_prefix_len+address_str->len; /*space included in MY_VIA*/
2734 memcpy(line_buf, MY_VIA, MY_VIA_LEN);
2735 if (send_info->proto==PROTO_UDP){
2737 }else if (send_info->proto==PROTO_TCP){
2738 memcpy(line_buf+MY_VIA_LEN-4, "TCP ", 4);
2739 }else if (send_info->proto==PROTO_TLS){
2740 memcpy(line_buf+MY_VIA_LEN-4, "TLS ", 4);
2741 }else if (send_info->proto==PROTO_SCTP){
2742 memcpy(line_buf+MY_VIA_LEN-4, "SCTP ", 5);
2743 }else if (send_info->proto==PROTO_WS){
2744 if (unlikely(send_info->send_flags.f & SND_F_FORCE_SOCKET
2745 && send_info->send_sock)) {
2746 local_addr = send_info->send_sock->su;
2747 su_setport(&local_addr, 0); /* any local port will do */
2751 port = su_getport(&send_info->to);
2753 su2ip_addr(&ip, &send_info->to);
2754 con = tcpconn_get(send_info->id, &ip, port, from, 0);
2756 else if (likely(send_info->id))
2757 con = tcpconn_get(send_info->id, 0, 0, 0, 0);
2759 LM_CRIT("null_id & to\n"); pkg_free(line_buf);
2764 LM_WARN("TCP/TLS connection (id: %d) for WebSocket could not be found\n",
2770 if (con->rcv.proto==PROTO_WS) {
2771 memcpy(line_buf+MY_VIA_LEN-4, "WS ", 3);
2772 } else if (con->rcv.proto==PROTO_WSS) {
2773 memcpy(line_buf+MY_VIA_LEN-4, "WSS ", 4);
2776 LM_CRIT("unknown proto %d\n", con->rcv.proto);
2781 }else if (send_info->proto==PROTO_WSS){
2782 memcpy(line_buf+MY_VIA_LEN-4, "WSS ", 4);
2784 LM_CRIT("unknown proto %d\n", send_info->proto);
2788 /* add [] only if ipv6 address is used;
2789 * if using pre-set no check is made */
2790 if (send_sock->address.af==AF_INET6) {
2791 /* lightweight safety checks if brackets set
2792 * or non-ipv6 (e.g., advertised hostname) */
2793 if(address_str->s[0] != '['
2794 && memchr(address_str->s, ':', address_str->len)!=NULL) {
2795 line_buf[via_prefix_len]='[';
2796 line_buf[via_prefix_len+1+address_str->len]=']';
2798 via_len+=2; /* [ ]*/
2801 memcpy(line_buf+via_prefix_len+extra_len, address_str->s,
2803 if ((send_sock->port_no!=SIP_PORT) ||
2804 (port_str!=&send_sock->port_no_str)){
2805 line_buf[via_len]=':'; via_len++;
2806 memcpy(line_buf+via_len, port_str->s, port_str->len);
2807 via_len+=port_str->len;
2810 /* branch parameter */
2812 memcpy(line_buf+via_len, MY_BRANCH, MY_BRANCH_LEN );
2813 via_len+=MY_BRANCH_LEN;
2814 memcpy(line_buf+via_len, branch->s, branch->len );
2815 via_len+=branch->len;
2819 memcpy(line_buf+via_len, extra_params->s, extra_params->len);
2820 via_len+=extra_params->len;
2825 memcpy(line_buf+via_len, COMP_PARAM, COMP_PARAM_LEN);
2826 via_len+=COMP_PARAM_LEN;
2827 memcpy(line_buf+via_len, comp_name, comp_name_len);
2828 via_len+=comp_name_len;
2832 memcpy(line_buf+via_len, CRLF, CRLF_LEN);
2834 line_buf[via_len]=0; /* null terminate the string*/
2840 /* creates a via header honoring the protocol of the incomming socket
2841 * msg is an optional parameter */
2842 char* create_via_hf( unsigned int *len,
2843 struct sip_msg *msg,
2844 struct dest_info* send_info /* where to send the reply */,
2852 #if defined USE_TCP || defined USE_SCTP
2854 unsigned int id_len;
2864 #if defined USE_TCP || defined USE_SCTP
2868 (msg->rcv.proto==PROTO_TCP)
2870 || (msg->rcv.proto==PROTO_TLS)
2874 #endif /* USE_SCTP */
2875 #endif /* USE_TCP */
2877 (msg->rcv.proto==PROTO_SCTP)
2878 #endif /* USE_SCTP */
2880 if ((id_buf=id_builder(msg, &id_len))==0){
2881 LM_ERR("id_builder failed\n");
2882 return 0; /* we don't need to free anything,
2883 nothing alloc'ed yet*/
2885 LM_DBG("id added: <%.*s>, rcv proto=%d\n",
2886 (int)id_len, id_buf, msg->rcv.proto);
2887 extra_params.s=id_buf;
2888 extra_params.len=id_len;
2890 #endif /* USE_TCP || USE_SCTP */
2892 /* test and add rport parameter to local via - rfc3581 */
2893 if(msg && msg->msg_flags&FL_ADD_LOCAL_RPORT) {
2894 /* params so far + ';rport' + '\0' */
2895 via = (char*)pkg_malloc(extra_params.len+RPORT_LEN);
2897 LM_ERR("building local rport via param failed\n");
2898 if (extra_params.s) pkg_free(extra_params.s);
2901 if(extra_params.len!=0) {
2902 memcpy(via, extra_params.s, extra_params.len);
2903 pkg_free(extra_params.s);
2905 memcpy(via + extra_params.len, RPORT, RPORT_LEN-1);
2906 extra_params.s = via;
2907 extra_params.len += RPORT_LEN-1;
2908 extra_params.s[extra_params.len]='\0';
2911 /* test and add srvid parameter to local via */
2912 if(msg && (msg->msg_flags&FL_ADD_SRVID) && server_id!=0) {
2913 slen = snprintf(sbuf, 24, ";srvid=%u", (unsigned int)server_id);
2914 if(slen<=0 || slen>=24) {
2915 LM_WARN("failed to build srvid parameter");
2917 via = (char*)pkg_malloc(extra_params.len+slen+1);
2919 LM_ERR("building srvid param failed\n");
2920 if (extra_params.s) pkg_free(extra_params.s);
2923 if(extra_params.len != 0) {
2924 memcpy(via, extra_params.s, extra_params.len);
2925 pkg_free(extra_params.s);
2927 memcpy(via + extra_params.len, sbuf, slen);
2928 extra_params.s = via;
2929 extra_params.len += slen;
2930 extra_params.s[extra_params.len] = '\0';
2934 set_hostport(&hp, msg);
2935 via = via_builder( len, send_info, branch,
2936 extra_params.len?&extra_params:0, &hp);
2938 /* we do not need extra_params any more, already in the new via header */
2939 if (extra_params.s) pkg_free(extra_params.s);
2943 /* builds a char* buffer from message headers without body
2944 * first line is excluded in case of skip_first_line=1
2945 * error is set -1 if the memory allocation failes
2947 char * build_only_headers( struct sip_msg* msg, int skip_first_line,
2948 unsigned int *returned_len,
2950 struct dest_info* send_info)
2952 char *buf, *new_buf;
2953 unsigned int offset, s_offset, len, new_len;
2957 if (skip_first_line)
2958 s_offset = msg->headers->name.s - buf;
2962 /* original length without body, and without final \r\n */
2963 len = msg->unparsed - buf;
2964 /* new msg length */
2965 new_len = len - /* original length */
2966 s_offset + /* skipped first line */
2967 lumps_len(msg, msg->add_rm, send_info); /* lumps */
2974 new_buf = (char *)pkg_malloc(new_len+1);
2976 LM_ERR("Not enough memory\n");
2983 /* copy message lumps */
2984 process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, FLAG_MSG_ALL);
2985 /* copy the rest of the message without body */
2986 if (len > s_offset) {
2987 memcpy(new_buf+offset, buf+s_offset, len-s_offset);
2988 offset += (len-s_offset);
2990 new_buf[offset] = 0;
2992 *returned_len = offset;
2996 /* builds a char* buffer from message body
2997 * error is set -1 if the memory allocation failes
2999 char * build_body( struct sip_msg* msg,
3000 unsigned int *returned_len,
3002 struct dest_info* send_info)
3004 char *buf, *new_buf, *body;