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