/src/kamailio/src/core/msg_translator.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-2003 FhG Fokus |
3 | | * |
4 | | * This file is part of Kamailio, a free SIP server. |
5 | | * |
6 | | * Kamailio is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * Kamailio is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * |
20 | | * |
21 | | * |
22 | | */ |
23 | | /** Via special params: |
24 | | * requests: |
25 | | * - if the address in via is different from the src_ip or an existing |
26 | | * received=something is found, received=src_ip is added (and any preexisting |
27 | | * received is deleted). received is added as the first via parameter if no |
28 | | * receive is previously present or over the old receive. |
29 | | * - if the original via contains rport / rport=something or msg->msg_flags |
30 | | * FL_FORCE_RPORT is set (e.g. script force_rport() cmd) rport=src_port |
31 | | * is added (over previous rport / as first via param or after received |
32 | | * if no received was present and received is added too) |
33 | | * local replies: |
34 | | * (see also sl_send_reply) |
35 | | * - rport and received are added in mostly the same way as for requests, but |
36 | | * in the reverse order (first rport and then received). See also |
37 | | * limitations. |
38 | | * - if reply_to_via is set (default off) the local reply will be sent to |
39 | | * the address in via (received is ignored since it was not set by us). The |
40 | | * destination port is either the message source port if via contains rport |
41 | | * or the FL_FORCE_RPORT flag is set or the port from the via. If either |
42 | | * port or rport are present a normal dns lookup (instead of a srv lookup) |
43 | | * is performed on the address. If no port is present and a srv lookup is |
44 | | * performed the port is taken from the srv lookup. If the srv lookup failed |
45 | | * or it was not performed, the port is set to the default sip port (5060). |
46 | | * - if reply_to_via is off (default) the local reply is sent to the message |
47 | | * source ip address. The destination port is set to the source port if |
48 | | * rport is present or FL_FORCE_RPORT flag is set, to the via port or to |
49 | | * the default sip port (5060) if neither rport or via port are present. |
50 | | * "normal" replies: |
51 | | * - if received is present the message is sent to the received address else |
52 | | * if no port is present (neither a normal via port or rport) a dns srv |
53 | | * lookup is performed on the host part and the reply is sent to the |
54 | | * resulting ip. If a port is present or the host part is an ip address |
55 | | * the dns lookup will be a "normal" one (A or AAAA). |
56 | | * - if rport is present, its value will be used as the destination port |
57 | | * (and this will also disable srv lookups) |
58 | | * - if no port is present the destination port will be taken from the srv |
59 | | * lookup. If the srv lookup fails or is not performed (e.g. ip address |
60 | | * in host) the destination port will be set to the default sip port (5060). |
61 | | * |
62 | | * Known limitations: |
63 | | * - when locally replying to a message, rport and received will be appended to |
64 | | * the via header parameters (for forwarded requests they are inserted at the |
65 | | * beginning). |
66 | | * - a locally generated reply might get two received via parameters if a |
67 | | * received is already present in the original message (this should not |
68 | | * happen though, but ...) |
69 | | * |
70 | | *--andrei |
71 | | */ |
72 | | |
73 | | /*! |
74 | | * \file |
75 | | * \brief Kamailio core :: Message translations |
76 | | * \ingroup core |
77 | | * Module: \ref core |
78 | | */ |
79 | | |
80 | | #include <sys/types.h> |
81 | | #include <sys/socket.h> |
82 | | #include <netdb.h> |
83 | | #include <string.h> |
84 | | #include <stdio.h> |
85 | | #include <stdlib.h> |
86 | | |
87 | | #include "comp_defs.h" |
88 | | #include "msg_translator.h" |
89 | | #include "globals.h" |
90 | | #include "error.h" |
91 | | #include "mem/mem.h" |
92 | | #include "dprint.h" |
93 | | #include "config.h" |
94 | | #include "data_lump.h" |
95 | | #include "data_lump_rpl.h" |
96 | | #include "ip_addr.h" |
97 | | #include "resolve.h" |
98 | | #include "ut.h" |
99 | | #include "pt.h" |
100 | | #include "cfg/cfg.h" |
101 | | #include "parser/parse_to.h" |
102 | | #include "parser/parse_param.h" |
103 | | #include "forward.h" |
104 | | #include "str_list.h" |
105 | | #include "pvapi.h" |
106 | | #include "xavp.h" |
107 | | #include "rand/kam_rand.h" |
108 | | |
109 | | #define append_str_trans(_dest, _src, _len, _msg) \ |
110 | 0 | append_str((_dest), (_src), (_len)); |
111 | | |
112 | | extern char version[]; |
113 | | extern int version_len; |
114 | | |
115 | | str _ksr_xavp_via_params = STR_NULL; |
116 | | str _ksr_xavp_via_fields = STR_NULL; |
117 | | str _ksr_xavp_via_reply_params = STR_NULL; |
118 | | int ksr_local_rport = 0; |
119 | | |
120 | | /** per process fixup function for global_req_flags. |
121 | | * It should be called from the configuration framework. |
122 | | */ |
123 | | void fix_global_req_flags(str *gname, str *name) |
124 | 0 | { |
125 | 0 | global_req_flags = 0; |
126 | 0 | switch(cfg_get(core, core_cfg, udp_mtu_try_proto)) { |
127 | 0 | case PROTO_NONE: |
128 | 0 | case PROTO_UDP: |
129 | | /* do nothing */ |
130 | 0 | break; |
131 | 0 | case PROTO_TCP: |
132 | 0 | global_req_flags |= FL_MTU_TCP_FB; |
133 | 0 | break; |
134 | 0 | case PROTO_TLS: |
135 | 0 | global_req_flags |= FL_MTU_TLS_FB; |
136 | 0 | break; |
137 | 0 | case PROTO_SCTP: |
138 | 0 | global_req_flags |= FL_MTU_SCTP_FB; |
139 | 0 | break; |
140 | 0 | } |
141 | 0 | if(cfg_get(core, core_cfg, force_rport)) |
142 | 0 | global_req_flags |= FL_FORCE_RPORT; |
143 | 0 | } |
144 | | |
145 | | |
146 | | /* checks if ip is in host(name) and ?host(ip)=name? |
147 | | * ip must be in network byte order! |
148 | | * resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made |
149 | | * return 0 if equal */ |
150 | | static int check_via_address( |
151 | | struct ip_addr *ip, str *name, unsigned short port, int resolver) |
152 | 0 | { |
153 | 0 | struct hostent *he; |
154 | 0 | int i; |
155 | 0 | char *s; |
156 | 0 | int len; |
157 | 0 | char lproto; |
158 | | |
159 | | /* maybe we are lucky and name it's an ip */ |
160 | 0 | s = ip_addr2a(ip); |
161 | 0 | if(s) { |
162 | 0 | LM_DBG("(%s, %.*s, %d)\n", s, name->len, name->s, resolver); |
163 | |
|
164 | 0 | len = strlen(s); |
165 | | |
166 | | /* check if name->s is an ipv6 address or an ipv6 address ref. */ |
167 | 0 | if((ip->af == AF_INET6) |
168 | 0 | && (((len == name->len) |
169 | 0 | && (strncasecmp(name->s, s, name->len) == 0)) |
170 | 0 | || ((len == (name->len - 2)) && (name->s[0] == '[') |
171 | 0 | && (name->s[name->len - 1] == ']') |
172 | 0 | && (strncasecmp(name->s + 1, s, len) == 0)))) { |
173 | 0 | return 0; |
174 | 0 | } else { |
175 | 0 | if(unlikely(name->s == NULL)) { |
176 | 0 | LM_CRIT("invalid Via host name\n"); |
177 | 0 | return -1; |
178 | 0 | } |
179 | 0 | if(len == name->len && (strncmp(name->s, s, name->len) == 0)) |
180 | 0 | return 0; |
181 | 0 | } |
182 | 0 | } else { |
183 | 0 | LM_CRIT("could not convert ip address\n"); |
184 | 0 | return -1; |
185 | 0 | } |
186 | | |
187 | 0 | if(port == 0) |
188 | 0 | port = SIP_PORT; |
189 | 0 | if(resolver & DO_DNS) { |
190 | 0 | LM_DBG("doing dns lookup\n"); |
191 | | /* try all names ips */ |
192 | 0 | lproto = PROTO_NONE; |
193 | 0 | he = sip_resolvehost(name, &port, &lproto); /* don't use naptr */ |
194 | 0 | if(he && ip->af == he->h_addrtype) { |
195 | 0 | for(i = 0; he && he->h_addr_list[i]; i++) { |
196 | 0 | if(memcmp(&he->h_addr_list[i], ip->u.addr, ip->len) == 0) |
197 | 0 | return 0; |
198 | 0 | } |
199 | 0 | } |
200 | 0 | } |
201 | 0 | if(resolver & DO_REV_DNS) { |
202 | 0 | LM_DBG("doing rev. dns lookup\n"); |
203 | | /* try reverse dns */ |
204 | 0 | he = rev_resolvehost(ip); |
205 | 0 | if(he && (strncmp(he->h_name, name->s, name->len) == 0)) |
206 | 0 | return 0; |
207 | 0 | for(i = 0; he && he->h_aliases[i]; i++) { |
208 | 0 | if(strncmp(he->h_aliases[i], name->s, name->len) == 0) |
209 | 0 | return 0; |
210 | 0 | } |
211 | 0 | } |
212 | 0 | return -1; |
213 | 0 | } |
214 | | |
215 | | |
216 | | /* check if IP address in Via != source IP address of signaling, |
217 | | * or the sender requires adding rport or received values */ |
218 | | int received_test(struct sip_msg *msg) |
219 | 0 | { |
220 | 0 | int rcvd; |
221 | |
|
222 | 0 | rcvd = msg->via1->received || msg->via1->rport |
223 | 0 | || check_via_address(&msg->rcv.src_ip, &msg->via1->host, |
224 | 0 | msg->via1->port, received_dns); |
225 | 0 | return rcvd; |
226 | 0 | } |
227 | | |
228 | | /* check if IP address in Via != source IP address of signaling */ |
229 | | int received_via_test(struct sip_msg *msg) |
230 | 0 | { |
231 | 0 | int rcvd; |
232 | |
|
233 | 0 | rcvd = (check_via_address(&msg->rcv.src_ip, &msg->via1->host, |
234 | 0 | msg->via1->port, received_dns) |
235 | 0 | != 0); |
236 | 0 | return rcvd; |
237 | 0 | } |
238 | | |
239 | | static char *warning_builder(struct sip_msg *msg, unsigned int *returned_len) |
240 | 0 | { |
241 | 0 | static char buf[MAX_WARNING_LEN]; |
242 | 0 | str *foo; |
243 | 0 | int print_len, l; |
244 | 0 | int clen; |
245 | 0 | char *t; |
246 | |
|
247 | 0 | #define str_print(string, string_len) \ |
248 | 0 | do { \ |
249 | 0 | l = (string_len); \ |
250 | 0 | if((clen + l) > MAX_WARNING_LEN) \ |
251 | 0 | goto error_overflow; \ |
252 | 0 | memcpy(buf + clen, (string), l); \ |
253 | 0 | clen += l; \ |
254 | 0 | } while(0) |
255 | |
|
256 | 0 | #define str_lenpair_print(string, string_len, string2, string2_len) \ |
257 | 0 | do { \ |
258 | 0 | str_print(string, string_len); \ |
259 | 0 | str_print(string2, string2_len); \ |
260 | 0 | } while(0) |
261 | |
|
262 | 0 | #define str_pair_print(string, string2, string2_len) \ |
263 | 0 | str_lenpair_print((string), strlen((string)), (string2), (string2_len)) |
264 | |
|
265 | 0 | #define str_int_print(string, intval) \ |
266 | 0 | do { \ |
267 | 0 | t = int2str((intval), &print_len); \ |
268 | 0 | str_pair_print(string, t, print_len); \ |
269 | 0 | } while(0) |
270 | |
|
271 | 0 | #define str_su_print(sockaddr) \ |
272 | 0 | do { \ |
273 | 0 | t = su2a(&sockaddr, sizeof(sockaddr)); \ |
274 | 0 | print_len = strlen(t); \ |
275 | 0 | str_print(t, print_len); \ |
276 | 0 | } while(0) |
277 | |
|
278 | 0 | #define str_ipaddr_print(string, ipaddr_val) \ |
279 | 0 | do { \ |
280 | 0 | t = ip_addr2a((ipaddr_val)); \ |
281 | 0 | print_len = strlen(t); \ |
282 | 0 | str_pair_print(string, t, print_len); \ |
283 | 0 | } while(0) |
284 | |
|
285 | 0 | clen = 0; |
286 | 0 | str_print(WARNING, WARNING_LEN); |
287 | 0 | str_su_print(msg->rcv.bind_address->su); |
288 | 0 | str_print(WARNING_PHRASE, WARNING_PHRASE_LEN); |
289 | | |
290 | | /*adding out_uri*/ |
291 | 0 | if(msg->new_uri.s) |
292 | 0 | foo = &(msg->new_uri); |
293 | 0 | else |
294 | 0 | foo = &(msg->first_line.u.request.uri); |
295 | | /* pid= */ |
296 | 0 | str_int_print(" pid=", my_pid()); |
297 | | /* req_src_ip= */ |
298 | 0 | str_ipaddr_print(" req_src_ip=", &msg->rcv.src_ip); |
299 | 0 | str_int_print(" req_src_port=", msg->rcv.src_port); |
300 | 0 | str_pair_print(" in_uri=", msg->first_line.u.request.uri.s, |
301 | 0 | msg->first_line.u.request.uri.len); |
302 | 0 | str_pair_print(" out_uri=", foo->s, foo->len); |
303 | 0 | str_pair_print(" via_cnt", |
304 | 0 | (msg->parsed_flag & HDR_EOH_F) == HDR_EOH_F ? "=" : ">", 1); |
305 | 0 | str_int_print("=", via_cnt); |
306 | 0 | if(clen < MAX_WARNING_LEN) { |
307 | 0 | buf[clen] = '"'; |
308 | 0 | clen++; |
309 | 0 | } else |
310 | 0 | goto error_overflow; |
311 | | |
312 | | |
313 | 0 | *returned_len = clen; |
314 | 0 | return buf; |
315 | 0 | error_overflow: |
316 | 0 | LM_NOTICE("buffer size exceeded (probably too long URI)\n"); |
317 | 0 | *returned_len = 0; |
318 | 0 | return 0; |
319 | 0 | } |
320 | | |
321 | | |
322 | | char *received_builder(struct sip_msg *msg, unsigned int *received_len) |
323 | 0 | { |
324 | 0 | char *buf; |
325 | 0 | int len; |
326 | 0 | struct ip_addr *source_ip; |
327 | 0 | char *tmp; |
328 | 0 | int tmp_len; |
329 | |
|
330 | 0 | source_ip = &msg->rcv.src_ip; |
331 | |
|
332 | 0 | buf = pkg_malloc(sizeof(char) * MAX_RECEIVED_SIZE); |
333 | 0 | if(buf == 0) { |
334 | 0 | ser_error = E_OUT_OF_MEM; |
335 | 0 | PKG_MEM_ERROR; |
336 | 0 | return 0; |
337 | 0 | } |
338 | 0 | memcpy(buf, RECEIVED, RECEIVED_LEN); |
339 | 0 | if((tmp = ip_addr2a(source_ip)) == 0) { |
340 | 0 | pkg_free(buf); |
341 | 0 | return 0; /* error*/ |
342 | 0 | } |
343 | 0 | tmp_len = strlen(tmp); |
344 | 0 | len = RECEIVED_LEN + tmp_len; |
345 | |
|
346 | 0 | memcpy(buf + RECEIVED_LEN, tmp, tmp_len); |
347 | 0 | buf[len] = 0; /*null terminate it */ |
348 | |
|
349 | 0 | *received_len = len; |
350 | 0 | return buf; |
351 | 0 | } |
352 | | |
353 | | |
354 | | char *rport_builder(struct sip_msg *msg, unsigned int *rport_len) |
355 | 0 | { |
356 | 0 | char *buf; |
357 | 0 | char *tmp; |
358 | 0 | int tmp_len; |
359 | 0 | int len; |
360 | |
|
361 | 0 | tmp_len = 0; |
362 | 0 | tmp = int2str(msg->rcv.src_port, &tmp_len); |
363 | 0 | len = RPORT_LEN + tmp_len; |
364 | 0 | buf = pkg_malloc(sizeof(char) * (len + 1)); /* space for null term */ |
365 | 0 | if(buf == 0) { |
366 | 0 | ser_error = E_OUT_OF_MEM; |
367 | 0 | PKG_MEM_ERROR; |
368 | 0 | return 0; |
369 | 0 | } |
370 | 0 | memcpy(buf, RPORT, RPORT_LEN); |
371 | 0 | memcpy(buf + RPORT_LEN, tmp, tmp_len); |
372 | 0 | buf[len] = 0; /*null terminate it*/ |
373 | |
|
374 | 0 | *rport_len = len; |
375 | 0 | return buf; |
376 | 0 | } |
377 | | |
378 | | |
379 | | char *id_builder(struct sip_msg *msg, unsigned int *id_len) |
380 | 0 | { |
381 | 0 | char *buf; |
382 | 0 | int len, value_len; |
383 | 0 | char revhex[sizeof(int) * 2]; |
384 | 0 | char *p; |
385 | 0 | int size; |
386 | |
|
387 | 0 | size = sizeof(int) * 2; |
388 | 0 | p = &revhex[0]; |
389 | 0 | if(int2reverse_hex(&p, &size, msg->rcv.proto_reserved1) == -1) { |
390 | 0 | LM_CRIT("not enough space for id\n"); |
391 | 0 | return 0; |
392 | 0 | } |
393 | 0 | value_len = p - &revhex[0]; |
394 | 0 | len = ID_PARAM_LEN + value_len; |
395 | 0 | buf = pkg_malloc(sizeof(char) * (len + 1)); /* place for ending \0 */ |
396 | 0 | if(buf == 0) { |
397 | 0 | ser_error = E_OUT_OF_MEM; |
398 | 0 | PKG_MEM_ERROR; |
399 | 0 | return 0; |
400 | 0 | } |
401 | 0 | memcpy(buf, ID_PARAM, ID_PARAM_LEN); |
402 | 0 | memcpy(buf + ID_PARAM_LEN, revhex, value_len); |
403 | 0 | buf[len] = 0; /* null terminate it */ |
404 | 0 | *id_len = len; |
405 | 0 | return buf; |
406 | 0 | } |
407 | | |
408 | | |
409 | | char *clen_builder(struct sip_msg *msg, int *clen_len, int diff, int body_only) |
410 | 0 | { |
411 | 0 | char *buf; |
412 | 0 | int len; |
413 | 0 | int value; |
414 | 0 | char *value_s; |
415 | 0 | int value_len; |
416 | 0 | char *body; |
417 | | |
418 | |
|
419 | 0 | body = get_body(msg); |
420 | 0 | if(body == 0) { |
421 | 0 | ser_error = E_BAD_REQ; |
422 | 0 | LM_ERR("no message body found (missing crlf?) [[%.*s]]\n", msg->len, |
423 | 0 | msg->buf); |
424 | 0 | return 0; |
425 | 0 | } |
426 | 0 | value = msg->len - (int)(body - msg->buf) + diff; |
427 | 0 | value_s = int2str(value, &value_len); |
428 | 0 | LM_DBG("content-length: %d (%s)\n", value, value_s); |
429 | |
|
430 | 0 | if(body_only) { |
431 | 0 | len = value_len; |
432 | 0 | } else { |
433 | 0 | len = CONTENT_LENGTH_LEN + value_len + CRLF_LEN; |
434 | 0 | } |
435 | 0 | buf = pkg_malloc(sizeof(char) * (len + 1)); |
436 | 0 | if(buf == 0) { |
437 | 0 | ser_error = E_OUT_OF_MEM; |
438 | 0 | PKG_MEM_ERROR; |
439 | 0 | return 0; |
440 | 0 | } |
441 | 0 | if(body_only) { |
442 | 0 | memcpy(buf, value_s, value_len); |
443 | 0 | } else { |
444 | 0 | memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN); |
445 | 0 | memcpy(buf + CONTENT_LENGTH_LEN, value_s, value_len); |
446 | 0 | memcpy(buf + CONTENT_LENGTH_LEN + value_len, CRLF, CRLF_LEN); |
447 | 0 | } |
448 | 0 | buf[len] = 0; /* null terminate it */ |
449 | 0 | *clen_len = len; |
450 | 0 | return buf; |
451 | 0 | } |
452 | | |
453 | | |
454 | | /* checks if a lump opt condition |
455 | | * returns 1 if cond is true, 0 if false */ |
456 | | static inline int lump_check_opt( |
457 | | struct lump *l, struct sip_msg *msg, struct dest_info *snd_i) |
458 | 0 | { |
459 | 0 | struct ip_addr *ip; |
460 | 0 | unsigned short port; |
461 | 0 | int proto; |
462 | |
|
463 | 0 | #define get_ip_port_proto \ |
464 | 0 | if((snd_i == 0) || (snd_i->send_sock == 0)) { \ |
465 | 0 | LM_CRIT("null send socket\n"); \ |
466 | 0 | return 1; /* we presume they are different :-) */ \ |
467 | 0 | } \ |
468 | 0 | if(msg->rcv.bind_address) { \ |
469 | 0 | ip = &msg->rcv.bind_address->address; \ |
470 | 0 | port = msg->rcv.bind_address->port_no; \ |
471 | 0 | proto = msg->rcv.bind_address->proto; \ |
472 | 0 | } else { \ |
473 | 0 | ip = &msg->rcv.dst_ip; \ |
474 | 0 | port = msg->rcv.dst_port; \ |
475 | 0 | proto = msg->rcv.proto; \ |
476 | 0 | } |
477 | |
|
478 | 0 | switch(l->u.cond) { |
479 | 0 | case COND_FALSE: |
480 | 0 | return 0; |
481 | 0 | case COND_TRUE: |
482 | 0 | LUMP_SET_COND_TRUE(l); |
483 | 0 | return 1; |
484 | 0 | case COND_IF_DIFF_REALMS: |
485 | 0 | get_ip_port_proto; |
486 | | /* faster tests first */ |
487 | 0 | if((port == snd_i->send_sock->port_no) |
488 | 0 | && (proto == snd_i->send_sock->proto) |
489 | 0 | && (msg->rcv.proto == snd_i->proto) && |
490 | | #ifdef USE_COMP |
491 | | (msg->rcv.comp == snd_i->comp) && |
492 | | #endif |
493 | 0 | (ip_addr_cmp(ip, &snd_i->send_sock->address))) |
494 | 0 | return 0; |
495 | 0 | else { |
496 | 0 | LUMP_SET_COND_TRUE(l); |
497 | 0 | return 1; |
498 | 0 | } |
499 | 0 | case COND_IF_DIFF_AF: |
500 | 0 | get_ip_port_proto; |
501 | 0 | if(ip->af != snd_i->send_sock->address.af) { |
502 | 0 | LUMP_SET_COND_TRUE(l); |
503 | 0 | return 1; |
504 | 0 | } else |
505 | 0 | return 0; |
506 | 0 | case COND_IF_DIFF_PROTO: |
507 | 0 | get_ip_port_proto; |
508 | 0 | if((proto != snd_i->send_sock->proto) |
509 | 0 | || (msg->rcv.proto != snd_i->proto)) { |
510 | 0 | LUMP_SET_COND_TRUE(l); |
511 | 0 | return 1; |
512 | 0 | } else |
513 | 0 | return 0; |
514 | 0 | case COND_IF_DIFF_PORT: |
515 | 0 | get_ip_port_proto; |
516 | 0 | if(port != snd_i->send_sock->port_no) { |
517 | 0 | LUMP_SET_COND_TRUE(l); |
518 | 0 | return 1; |
519 | 0 | } else |
520 | 0 | return 0; |
521 | 0 | case COND_IF_DIFF_IP: |
522 | 0 | get_ip_port_proto; |
523 | 0 | if(ip_addr_cmp(ip, &snd_i->send_sock->address)) |
524 | 0 | return 0; |
525 | 0 | else { |
526 | 0 | LUMP_SET_COND_TRUE(l); |
527 | 0 | return 1; |
528 | 0 | } |
529 | 0 | case COND_IF_RAND: |
530 | 0 | if(kam_rand() >= KAM_RAND_MAX / 2) { |
531 | 0 | LUMP_SET_COND_TRUE(l); |
532 | 0 | return 1; |
533 | 0 | } else |
534 | 0 | return 0; |
535 | 0 | default: |
536 | 0 | LM_CRIT("unknown lump condition %d\n", l->u.cond); |
537 | 0 | } |
538 | 0 | return 0; /* false */ |
539 | 0 | } |
540 | | |
541 | | |
542 | | /* computes the "unpacked" len of a lump list, |
543 | | code moved from build_req_from_req */ |
544 | | static inline int lumps_len( |
545 | | struct sip_msg *msg, struct lump *lumps, struct dest_info *send_info) |
546 | 0 | { |
547 | 0 | int s_offset; |
548 | 0 | int new_len; |
549 | 0 | struct lump *t; |
550 | 0 | struct lump *r; |
551 | 0 | str *send_address_str = NULL; |
552 | 0 | str *send_port_str = NULL; |
553 | 0 | int send_proto_id = PROTO_NONE; |
554 | 0 | str *recv_address_str = NULL; |
555 | 0 | str *recv_port_str = NULL; |
556 | 0 | int recv_port_no = 0; |
557 | 0 | int recv_proto_id = PROTO_NONE; |
558 | 0 | struct socket_info *send_sock; |
559 | | |
560 | |
|
561 | | #ifdef USE_COMP |
562 | | #define RCVCOMP_LUMP_LEN \ |
563 | | /* add;comp=xxx */ \ |
564 | | switch(msg->rcv.comp) { \ |
565 | | case COMP_NONE: \ |
566 | | break; \ |
567 | | case COMP_SIGCOMP: \ |
568 | | new_len += COMP_PARAM_LEN + SIGCOMP_NAME_LEN; \ |
569 | | break; \ |
570 | | case COMP_SERGZ: \ |
571 | | new_len += COMP_PARAM_LEN + SERGZ_NAME_LEN; \ |
572 | | break; \ |
573 | | default: \ |
574 | | LM_CRIT("unknown comp %d\n", msg->rcv.comp); \ |
575 | | } |
576 | | |
577 | | #define SENDCOMP_LUMP_LEN \ |
578 | | /* add;comp=xxx */ \ |
579 | | switch(send_info->comp) { \ |
580 | | case COMP_NONE: \ |
581 | | break; \ |
582 | | case COMP_SIGCOMP: \ |
583 | | new_len += COMP_PARAM_LEN + SIGCOMP_NAME_LEN; \ |
584 | | break; \ |
585 | | case COMP_SERGZ: \ |
586 | | new_len += COMP_PARAM_LEN + SERGZ_NAME_LEN; \ |
587 | | break; \ |
588 | | default: \ |
589 | | LM_CRIT("unknown comp %d\n", send_info->comp); \ |
590 | | } |
591 | | #else |
592 | 0 | #define RCVCOMP_LUMP_LEN |
593 | 0 | #define SENDCOMP_LUMP_LEN |
594 | 0 | #endif /*USE_COMP */ |
595 | |
|
596 | 0 | #define SUBST_LUMP_LEN(subst_l) \ |
597 | 0 | switch((subst_l)->u.subst) { \ |
598 | 0 | case SUBST_RCV_IP: \ |
599 | 0 | if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) { \ |
600 | 0 | new_len += recv_address_str->len; \ |
601 | 0 | if(msg->rcv.bind_address->address.af != AF_INET) \ |
602 | 0 | new_len += 2; \ |
603 | 0 | } else { \ |
604 | | /* FIXME */ \ |
605 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
606 | 0 | }; \ |
607 | 0 | break; \ |
608 | 0 | case SUBST_RCV_PORT: \ |
609 | 0 | if(msg->rcv.bind_address && STR_WITHVAL(recv_port_str)) { \ |
610 | 0 | new_len += recv_port_str->len; \ |
611 | 0 | } else { \ |
612 | | /* FIXME */ \ |
613 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
614 | 0 | }; \ |
615 | 0 | break; \ |
616 | 0 | case SUBST_RCV_PROTO: \ |
617 | 0 | if(msg->rcv.bind_address) { \ |
618 | 0 | switch(msg->rcv.bind_address->proto) { \ |
619 | 0 | case PROTO_NONE: \ |
620 | 0 | case PROTO_UDP: \ |
621 | 0 | new_len += 3; \ |
622 | 0 | break; \ |
623 | 0 | case PROTO_TCP: \ |
624 | 0 | case PROTO_TLS: \ |
625 | 0 | switch(msg->rcv.proto) { \ |
626 | 0 | case PROTO_WS: \ |
627 | 0 | case PROTO_WSS: \ |
628 | 0 | new_len += 2; \ |
629 | 0 | break; \ |
630 | 0 | default: \ |
631 | 0 | new_len += 3; \ |
632 | 0 | break; \ |
633 | 0 | } \ |
634 | 0 | break; \ |
635 | 0 | case PROTO_SCTP: \ |
636 | 0 | new_len += 4; \ |
637 | 0 | break; \ |
638 | 0 | default: \ |
639 | 0 | LM_CRIT("unknown proto %d\n", \ |
640 | 0 | msg->rcv.bind_address->proto); \ |
641 | 0 | } \ |
642 | 0 | } else { \ |
643 | | /* FIXME */ \ |
644 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
645 | 0 | }; \ |
646 | 0 | break; \ |
647 | 0 | case SUBST_RCV_ALL: \ |
648 | 0 | case SUBST_RCV_ALL_EX: \ |
649 | 0 | if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) { \ |
650 | 0 | new_len += recv_address_str->len; \ |
651 | 0 | if((msg->rcv.bind_address->address.af == AF_INET6) \ |
652 | 0 | && (recv_address_str->s[0] != '[') \ |
653 | 0 | && (memchr(recv_address_str->s, ':', \ |
654 | 0 | recv_address_str->len) \ |
655 | 0 | != NULL)) \ |
656 | 0 | new_len += 2; \ |
657 | 0 | if(recv_port_no != SIP_PORT && STR_WITHVAL(recv_port_str)) { \ |
658 | | /* add :port_no */ \ |
659 | 0 | new_len += 1 + recv_port_str->len; \ |
660 | 0 | } \ |
661 | | /*add;transport=xxx*/ \ |
662 | 0 | switch(recv_proto_id) { \ |
663 | 0 | case PROTO_NONE: \ |
664 | 0 | case PROTO_UDP: \ |
665 | 0 | break; /* udp is the default */ \ |
666 | 0 | case PROTO_TCP: \ |
667 | 0 | case PROTO_TLS: \ |
668 | 0 | switch(msg->rcv.proto) { \ |
669 | 0 | case PROTO_WS: \ |
670 | 0 | case PROTO_WSS: \ |
671 | 0 | new_len += TRANSPORT_PARAM_LEN + 2; \ |
672 | 0 | break; \ |
673 | 0 | default: \ |
674 | 0 | new_len += TRANSPORT_PARAM_LEN + 3; \ |
675 | 0 | break; \ |
676 | 0 | } \ |
677 | 0 | break; \ |
678 | 0 | case PROTO_WS: \ |
679 | 0 | case PROTO_WSS: \ |
680 | 0 | new_len += TRANSPORT_PARAM_LEN + 2; \ |
681 | 0 | break; \ |
682 | 0 | case PROTO_SCTP: \ |
683 | 0 | new_len += TRANSPORT_PARAM_LEN + 4; \ |
684 | 0 | break; \ |
685 | 0 | default: \ |
686 | 0 | LM_CRIT("unknown proto %d\n", \ |
687 | 0 | msg->rcv.bind_address->proto); \ |
688 | 0 | } \ |
689 | 0 | if((subst_l)->u.subst == SUBST_RCV_ALL_EX \ |
690 | 0 | && msg->rcv.bind_address->sockname.len > 0) { \ |
691 | 0 | new_len += SOCKNAME_PARAM_LEN \ |
692 | 0 | + msg->rcv.bind_address->sockname.len; \ |
693 | 0 | } \ |
694 | 0 | RCVCOMP_LUMP_LEN \ |
695 | 0 | } else { \ |
696 | | /* FIXME */ \ |
697 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
698 | 0 | }; \ |
699 | 0 | break; \ |
700 | 0 | case SUBST_SND_IP: \ |
701 | 0 | if(send_sock) { \ |
702 | 0 | new_len += send_address_str->len; \ |
703 | 0 | if(send_sock->address.af == AF_INET6 \ |
704 | 0 | && send_address_str->s[0] != '[') \ |
705 | 0 | new_len += 2; \ |
706 | 0 | } else { \ |
707 | 0 | LM_CRIT("FIXME: null send_sock\n"); \ |
708 | 0 | }; \ |
709 | 0 | break; \ |
710 | 0 | case SUBST_SND_PORT: \ |
711 | 0 | if(send_sock) { \ |
712 | 0 | new_len += send_port_str->len; \ |
713 | 0 | } else { \ |
714 | 0 | LM_CRIT("FIXME: null send_sock\n"); \ |
715 | 0 | }; \ |
716 | 0 | break; \ |
717 | 0 | case SUBST_SND_PROTO: \ |
718 | 0 | if(send_sock) { \ |
719 | 0 | switch(send_sock->proto) { \ |
720 | 0 | case PROTO_NONE: \ |
721 | 0 | case PROTO_UDP: \ |
722 | 0 | new_len += 3; \ |
723 | 0 | break; \ |
724 | 0 | case PROTO_TCP: \ |
725 | 0 | case PROTO_TLS: \ |
726 | 0 | switch(send_info->proto) { \ |
727 | 0 | case PROTO_WS: \ |
728 | 0 | case PROTO_WSS: \ |
729 | 0 | new_len += 2; \ |
730 | 0 | break; \ |
731 | 0 | default: \ |
732 | 0 | new_len += 3; \ |
733 | 0 | break; \ |
734 | 0 | } \ |
735 | 0 | break; \ |
736 | 0 | case PROTO_SCTP: \ |
737 | 0 | new_len += 4; \ |
738 | 0 | break; \ |
739 | 0 | default: \ |
740 | 0 | LM_CRIT("unknown proto %d\n", send_sock->proto); \ |
741 | 0 | } \ |
742 | 0 | } else { \ |
743 | 0 | LM_CRIT("FIXME: null send_sock\n"); \ |
744 | 0 | }; \ |
745 | 0 | break; \ |
746 | 0 | case SUBST_SND_ALL: \ |
747 | 0 | case SUBST_SND_ALL_EX: \ |
748 | 0 | if(send_sock) { \ |
749 | 0 | new_len += send_address_str->len; \ |
750 | 0 | if((send_sock->address.af == AF_INET6) \ |
751 | 0 | && (send_address_str->s[0] != '[') \ |
752 | 0 | && (memchr(send_address_str->s, ':', \ |
753 | 0 | send_address_str->len) \ |
754 | 0 | != NULL)) \ |
755 | 0 | new_len += 2; \ |
756 | 0 | if((send_sock->port_no != SIP_PORT) \ |
757 | 0 | || (send_port_str != &(send_sock->port_no_str))) { \ |
758 | | /* add :port_no */ \ |
759 | 0 | new_len += 1 + send_port_str->len; \ |
760 | 0 | } \ |
761 | | /*add;transport=xxx*/ \ |
762 | 0 | switch(send_proto_id) { \ |
763 | 0 | case PROTO_NONE: \ |
764 | 0 | case PROTO_UDP: \ |
765 | 0 | break; /* udp is the default */ \ |
766 | 0 | case PROTO_TCP: \ |
767 | 0 | case PROTO_TLS: \ |
768 | 0 | switch(send_info->proto) { \ |
769 | 0 | case PROTO_WS: \ |
770 | 0 | case PROTO_WSS: \ |
771 | 0 | new_len += TRANSPORT_PARAM_LEN + 2; \ |
772 | 0 | break; \ |
773 | 0 | default: \ |
774 | 0 | new_len += TRANSPORT_PARAM_LEN + 3; \ |
775 | 0 | break; \ |
776 | 0 | } \ |
777 | 0 | break; \ |
778 | 0 | case PROTO_WS: \ |
779 | 0 | case PROTO_WSS: \ |
780 | 0 | new_len += TRANSPORT_PARAM_LEN + 2; \ |
781 | 0 | break; \ |
782 | 0 | case PROTO_SCTP: \ |
783 | 0 | new_len += TRANSPORT_PARAM_LEN + 4; \ |
784 | 0 | break; \ |
785 | 0 | default: \ |
786 | 0 | LM_CRIT("unknown proto %d\n", send_sock->proto); \ |
787 | 0 | } \ |
788 | 0 | if((subst_l)->u.subst == SUBST_SND_ALL_EX \ |
789 | 0 | && send_sock->sockname.len > 0) { \ |
790 | 0 | new_len += SOCKNAME_PARAM_LEN + send_sock->sockname.len; \ |
791 | 0 | } \ |
792 | 0 | SENDCOMP_LUMP_LEN \ |
793 | 0 | } else { \ |
794 | | /* FIXME */ \ |
795 | 0 | LM_CRIT("FIXME: null send_sock\n"); \ |
796 | 0 | }; \ |
797 | 0 | break; \ |
798 | 0 | case SUBST_NOP: /* do nothing */ \ |
799 | 0 | break; \ |
800 | 0 | default: \ |
801 | 0 | LM_CRIT("unknown subst type %d\n", (subst_l)->u.subst); \ |
802 | 0 | } |
803 | |
|
804 | 0 | if(send_info) { |
805 | 0 | send_sock = send_info->send_sock; |
806 | 0 | } else { |
807 | 0 | send_sock = 0; |
808 | 0 | }; |
809 | 0 | s_offset = 0; |
810 | 0 | new_len = 0; |
811 | | /* init send_address_str & send_port_str */ |
812 | 0 | if(send_sock && send_sock->useinfo.name.len > 0) |
813 | 0 | send_address_str = &(send_sock->useinfo.name); |
814 | 0 | else if(msg->set_global_address.len) |
815 | 0 | send_address_str = &(msg->set_global_address); |
816 | 0 | else |
817 | 0 | send_address_str = &(send_sock->address_str); |
818 | 0 | if(send_sock && send_sock->useinfo.port_no > 0) |
819 | 0 | send_port_str = &(send_sock->useinfo.port_no_str); |
820 | 0 | else if(msg->set_global_port.len) |
821 | 0 | send_port_str = &(msg->set_global_port); |
822 | 0 | else |
823 | 0 | send_port_str = &(send_sock->port_no_str); |
824 | 0 | if(send_sock) { |
825 | 0 | if(send_sock->useinfo.proto != PROTO_NONE) |
826 | 0 | send_proto_id = send_sock->useinfo.proto; |
827 | 0 | else |
828 | 0 | send_proto_id = send_sock->proto; |
829 | 0 | } |
830 | | /* init recv_address_str, recv_port_str & recv_port_no */ |
831 | 0 | if(msg->rcv.bind_address) { |
832 | 0 | if(msg->rcv.bind_address->useinfo.name.len > 0) |
833 | 0 | recv_address_str = &(msg->rcv.bind_address->useinfo.name); |
834 | 0 | else |
835 | 0 | recv_address_str = &(msg->rcv.bind_address->address_str); |
836 | 0 | if(msg->rcv.bind_address->useinfo.port_no > 0) { |
837 | 0 | recv_port_str = &(msg->rcv.bind_address->useinfo.port_no_str); |
838 | 0 | recv_port_no = msg->rcv.bind_address->useinfo.port_no; |
839 | 0 | } else { |
840 | 0 | recv_port_str = &(msg->rcv.bind_address->port_no_str); |
841 | 0 | recv_port_no = msg->rcv.bind_address->port_no; |
842 | 0 | } |
843 | 0 | if(msg->rcv.bind_address->useinfo.proto != PROTO_NONE) { |
844 | 0 | recv_proto_id = msg->rcv.bind_address->useinfo.proto; |
845 | 0 | } else { |
846 | 0 | recv_proto_id = msg->rcv.bind_address->proto; |
847 | 0 | } |
848 | 0 | } |
849 | |
|
850 | 0 | for(t = lumps; t; t = t->next) { |
851 | | /* skip if this is an OPT lump and the condition is not satisfied */ |
852 | 0 | if((t->op == LUMP_ADD_OPT) && !lump_check_opt(t, msg, send_info)) |
853 | 0 | continue; |
854 | 0 | for(r = t->before; r; r = r->before) { |
855 | 0 | switch(r->op) { |
856 | 0 | case LUMP_ADD: |
857 | 0 | new_len += r->len; |
858 | 0 | break; |
859 | 0 | case LUMP_ADD_SUBST: |
860 | 0 | SUBST_LUMP_LEN(r); |
861 | 0 | break; |
862 | 0 | case LUMP_ADD_OPT: |
863 | | /* skip if this is an OPT lump and the condition is |
864 | | * not satisfied */ |
865 | 0 | if(!lump_check_opt(r, msg, send_info)) |
866 | 0 | goto skip_before; |
867 | 0 | break; |
868 | 0 | default: |
869 | | /* only ADD allowed for before/after */ |
870 | 0 | LM_CRIT("invalid op for data lump (%x)\n", r->op); |
871 | 0 | } |
872 | 0 | } |
873 | 0 | skip_before: |
874 | 0 | switch(t->op) { |
875 | 0 | case LUMP_ADD: |
876 | 0 | new_len += t->len; |
877 | 0 | break; |
878 | 0 | case LUMP_ADD_SUBST: |
879 | 0 | SUBST_LUMP_LEN(t); |
880 | 0 | break; |
881 | 0 | case LUMP_ADD_OPT: |
882 | | /* we don't do anything here, it's only a condition for |
883 | | * before & after */ |
884 | 0 | break; |
885 | 0 | case LUMP_DEL: |
886 | | /* fix overlapping deleted zones */ |
887 | 0 | if(t->u.offset < s_offset) { |
888 | | /* change len */ |
889 | 0 | if(t->len > s_offset - t->u.offset) |
890 | 0 | t->len -= s_offset - t->u.offset; |
891 | 0 | else |
892 | 0 | t->len = 0; |
893 | 0 | t->u.offset = s_offset; |
894 | 0 | } |
895 | 0 | s_offset = t->u.offset + t->len; |
896 | 0 | new_len -= t->len; |
897 | 0 | break; |
898 | 0 | case LUMP_NOP: |
899 | | /* fix offset if overlapping on a deleted zone */ |
900 | 0 | if(t->u.offset < s_offset) { |
901 | 0 | t->u.offset = s_offset; |
902 | 0 | } else |
903 | 0 | s_offset = t->u.offset; |
904 | | /* do nothing */ |
905 | 0 | break; |
906 | 0 | default: |
907 | 0 | LM_CRIT("invalid op for data lump (%x)\n", r->op); |
908 | 0 | } |
909 | 0 | for(r = t->after; r; r = r->after) { |
910 | 0 | switch(r->op) { |
911 | 0 | case LUMP_ADD: |
912 | 0 | new_len += r->len; |
913 | 0 | break; |
914 | 0 | case LUMP_ADD_SUBST: |
915 | 0 | SUBST_LUMP_LEN(r); |
916 | 0 | break; |
917 | 0 | case LUMP_ADD_OPT: |
918 | | /* skip if this is an OPT lump and the condition is |
919 | | * not satisfied */ |
920 | 0 | if(!lump_check_opt(r, msg, send_info)) |
921 | 0 | goto skip_after; |
922 | 0 | break; |
923 | 0 | default: |
924 | | /* only ADD allowed for before/after */ |
925 | 0 | LM_CRIT("invalid op for data lump (%x)\n", r->op); |
926 | 0 | } |
927 | 0 | } |
928 | 0 | skip_after:; /* to make gcc 3.* happy */ |
929 | 0 | } |
930 | 0 | return new_len; |
931 | 0 | #undef RCVCOMP_LUMP_LEN |
932 | 0 | #undef SENDCOMP_LUMP_LEN |
933 | 0 | } |
934 | | |
935 | | |
936 | | /* another helper functions, adds/Removes the lump, |
937 | | code moved form build_req_from_req */ |
938 | | |
939 | | void process_lumps(struct sip_msg *msg, struct lump *lumps, char *new_buf, |
940 | | unsigned int *new_buf_offs, unsigned int *orig_offs, |
941 | | struct dest_info *send_info, int flag) |
942 | 0 | { |
943 | 0 | struct lump *t; |
944 | 0 | struct lump *r; |
945 | 0 | char *orig; |
946 | 0 | int size; |
947 | 0 | int offset; |
948 | 0 | int s_offset; |
949 | 0 | str *send_address_str = NULL; |
950 | 0 | str *send_port_str = NULL; |
951 | 0 | int send_proto_id = PROTO_NONE; |
952 | 0 | str *recv_address_str = NULL; |
953 | 0 | str *recv_port_str = NULL; |
954 | 0 | int recv_port_no = 0; |
955 | 0 | int recv_proto_id = PROTO_NONE; |
956 | 0 | struct socket_info *send_sock; |
957 | |
|
958 | | #ifdef USE_COMP |
959 | | #define RCVCOMP_PARAM_ADD \ |
960 | | /* add ;comp=xxxx */ \ |
961 | | switch(msg->rcv.comp) { \ |
962 | | case COMP_NONE: \ |
963 | | break; \ |
964 | | case COMP_SIGCOMP: \ |
965 | | memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN); \ |
966 | | offset += COMP_PARAM_LEN; \ |
967 | | memcpy(new_buf + offset, SIGCOMP_NAME, SIGCOMP_NAME_LEN); \ |
968 | | offset += SIGCOMP_NAME_LEN; \ |
969 | | break; \ |
970 | | case COMP_SERGZ: \ |
971 | | memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN); \ |
972 | | offset += COMP_PARAM_LEN; \ |
973 | | memcpy(new_buf + offset, SERGZ_NAME, SERGZ_NAME_LEN); \ |
974 | | offset += SERGZ_NAME_LEN; \ |
975 | | break; \ |
976 | | default: \ |
977 | | LM_CRIT("unknown comp %d\n", msg->rcv.comp); \ |
978 | | } |
979 | | |
980 | | #define SENDCOMP_PARAM_ADD \ |
981 | | /* add ;comp=xxxx */ \ |
982 | | switch(send_info->comp) { \ |
983 | | case COMP_NONE: \ |
984 | | break; \ |
985 | | case COMP_SIGCOMP: \ |
986 | | memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN); \ |
987 | | offset += COMP_PARAM_LEN; \ |
988 | | memcpy(new_buf + offset, SIGCOMP_NAME, SIGCOMP_NAME_LEN); \ |
989 | | offset += SIGCOMP_NAME_LEN; \ |
990 | | break; \ |
991 | | case COMP_SERGZ: \ |
992 | | memcpy(new_buf + offset, COMP_PARAM, COMP_PARAM_LEN); \ |
993 | | offset += COMP_PARAM_LEN; \ |
994 | | memcpy(new_buf + offset, SERGZ_NAME, SERGZ_NAME_LEN); \ |
995 | | offset += SERGZ_NAME_LEN; \ |
996 | | break; \ |
997 | | default: \ |
998 | | LM_CRIT("unknown comp %d\n", msg->rcv.comp); \ |
999 | | } |
1000 | | #else |
1001 | 0 | #define RCVCOMP_PARAM_ADD |
1002 | 0 | #define SENDCOMP_PARAM_ADD |
1003 | 0 | #endif /* USE_COMP */ |
1004 | |
|
1005 | 0 | #define SUBST_LUMP(subst_l) \ |
1006 | 0 | switch((subst_l)->u.subst) { \ |
1007 | 0 | case SUBST_RCV_IP: \ |
1008 | 0 | if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) { \ |
1009 | 0 | if(msg->rcv.bind_address->address.af != AF_INET) { \ |
1010 | 0 | new_buf[offset] = '['; \ |
1011 | 0 | offset++; \ |
1012 | 0 | } \ |
1013 | 0 | memcpy(new_buf + offset, recv_address_str->s, \ |
1014 | 0 | recv_address_str->len); \ |
1015 | 0 | offset += recv_address_str->len; \ |
1016 | 0 | if(msg->rcv.bind_address->address.af != AF_INET) { \ |
1017 | 0 | new_buf[offset] = ']'; \ |
1018 | 0 | offset++; \ |
1019 | 0 | } \ |
1020 | 0 | } else { \ |
1021 | | /*FIXME*/ \ |
1022 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
1023 | 0 | }; \ |
1024 | 0 | break; \ |
1025 | 0 | case SUBST_RCV_PORT: \ |
1026 | 0 | if(msg->rcv.bind_address && STR_WITHVAL(recv_port_str)) { \ |
1027 | 0 | memcpy(new_buf + offset, recv_port_str->s, \ |
1028 | 0 | recv_port_str->len); \ |
1029 | 0 | offset += recv_port_str->len; \ |
1030 | 0 | } else { \ |
1031 | | /*FIXME*/ \ |
1032 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
1033 | 0 | }; \ |
1034 | 0 | break; \ |
1035 | 0 | case SUBST_RCV_ALL: \ |
1036 | 0 | case SUBST_RCV_ALL_EX: \ |
1037 | 0 | if(msg->rcv.bind_address && STR_WITHVAL(recv_address_str)) { \ |
1038 | | /* address */ \ |
1039 | 0 | if((msg->rcv.bind_address->address.af == AF_INET6) \ |
1040 | 0 | && (recv_address_str->s[0] != '[') \ |
1041 | 0 | && (memchr(recv_address_str->s, ':', \ |
1042 | 0 | recv_address_str->len) \ |
1043 | 0 | != NULL)) { \ |
1044 | 0 | new_buf[offset] = '['; \ |
1045 | 0 | offset++; \ |
1046 | 0 | } \ |
1047 | 0 | memcpy(new_buf + offset, recv_address_str->s, \ |
1048 | 0 | recv_address_str->len); \ |
1049 | 0 | offset += recv_address_str->len; \ |
1050 | 0 | if((msg->rcv.bind_address->address.af == AF_INET6) \ |
1051 | 0 | && (recv_address_str->s[0] != '[') \ |
1052 | 0 | && (memchr(recv_address_str->s, ':', \ |
1053 | 0 | recv_address_str->len) \ |
1054 | 0 | != NULL)) { \ |
1055 | 0 | new_buf[offset] = ']'; \ |
1056 | 0 | offset++; \ |
1057 | 0 | } \ |
1058 | | /* :port */ \ |
1059 | 0 | if(recv_port_no != SIP_PORT && STR_WITHVAL(recv_port_str)) { \ |
1060 | 0 | new_buf[offset] = ':'; \ |
1061 | 0 | offset++; \ |
1062 | 0 | memcpy(new_buf + offset, recv_port_str->s, \ |
1063 | 0 | recv_port_str->len); \ |
1064 | 0 | offset += recv_port_str->len; \ |
1065 | 0 | } \ |
1066 | 0 | switch(recv_proto_id) { \ |
1067 | 0 | case PROTO_NONE: \ |
1068 | 0 | case PROTO_UDP: \ |
1069 | 0 | break; /* nothing to do, udp is default*/ \ |
1070 | 0 | case PROTO_TCP: \ |
1071 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1072 | 0 | TRANSPORT_PARAM_LEN); \ |
1073 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1074 | 0 | if(msg->rcv.proto == PROTO_WS) { \ |
1075 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1076 | 0 | offset += 2; \ |
1077 | 0 | } else { \ |
1078 | 0 | memcpy(new_buf + offset, "tcp", 3); \ |
1079 | 0 | offset += 3; \ |
1080 | 0 | } \ |
1081 | 0 | break; \ |
1082 | 0 | case PROTO_TLS: \ |
1083 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1084 | 0 | TRANSPORT_PARAM_LEN); \ |
1085 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1086 | 0 | if(msg->rcv.proto == PROTO_WS \ |
1087 | 0 | || msg->rcv.proto == PROTO_WSS) { \ |
1088 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1089 | 0 | offset += 2; \ |
1090 | 0 | } else { \ |
1091 | 0 | memcpy(new_buf + offset, "tls", 3); \ |
1092 | 0 | offset += 3; \ |
1093 | 0 | } \ |
1094 | 0 | break; \ |
1095 | 0 | case PROTO_WS: \ |
1096 | 0 | case PROTO_WSS: \ |
1097 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1098 | 0 | TRANSPORT_PARAM_LEN); \ |
1099 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1100 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1101 | 0 | offset += 2; \ |
1102 | 0 | break; \ |
1103 | 0 | case PROTO_SCTP: \ |
1104 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1105 | 0 | TRANSPORT_PARAM_LEN); \ |
1106 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1107 | 0 | memcpy(new_buf + offset, "sctp", 4); \ |
1108 | 0 | offset += 4; \ |
1109 | 0 | break; \ |
1110 | 0 | default: \ |
1111 | 0 | LM_CRIT("unknown proto %d\n", \ |
1112 | 0 | msg->rcv.bind_address->proto); \ |
1113 | 0 | } \ |
1114 | 0 | if((subst_l)->u.subst == SUBST_RCV_ALL_EX \ |
1115 | 0 | && msg->rcv.bind_address->sockname.len > 0) { \ |
1116 | 0 | memcpy(new_buf + offset, SOCKNAME_PARAM, \ |
1117 | 0 | SOCKNAME_PARAM_LEN); \ |
1118 | 0 | offset += SOCKNAME_PARAM_LEN; \ |
1119 | 0 | memcpy(new_buf + offset, \ |
1120 | 0 | msg->rcv.bind_address->sockname.s, \ |
1121 | 0 | msg->rcv.bind_address->sockname.len); \ |
1122 | 0 | offset += msg->rcv.bind_address->sockname.len; \ |
1123 | 0 | } \ |
1124 | 0 | RCVCOMP_PARAM_ADD \ |
1125 | 0 | } else { \ |
1126 | | /*FIXME*/ \ |
1127 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
1128 | 0 | }; \ |
1129 | 0 | break; \ |
1130 | 0 | case SUBST_SND_IP: \ |
1131 | 0 | if(send_sock) { \ |
1132 | 0 | if((send_sock->address.af != AF_INET) \ |
1133 | 0 | && (send_address_str->s[0] != '[')) { \ |
1134 | 0 | new_buf[offset] = '['; \ |
1135 | 0 | offset++; \ |
1136 | 0 | } \ |
1137 | 0 | memcpy(new_buf + offset, send_address_str->s, \ |
1138 | 0 | send_address_str->len); \ |
1139 | 0 | offset += send_address_str->len; \ |
1140 | 0 | if((send_sock->address.af != AF_INET) \ |
1141 | 0 | && (send_address_str->s[0] != '[')) { \ |
1142 | 0 | new_buf[offset] = ']'; \ |
1143 | 0 | offset++; \ |
1144 | 0 | } \ |
1145 | 0 | } else { \ |
1146 | | /*FIXME*/ \ |
1147 | 0 | LM_CRIT("FIXME: null send_sock\n"); \ |
1148 | 0 | }; \ |
1149 | 0 | break; \ |
1150 | 0 | case SUBST_SND_PORT: \ |
1151 | 0 | if(send_sock) { \ |
1152 | 0 | memcpy(new_buf + offset, send_port_str->s, \ |
1153 | 0 | send_port_str->len); \ |
1154 | 0 | offset += send_port_str->len; \ |
1155 | 0 | } else { \ |
1156 | | /*FIXME*/ \ |
1157 | 0 | LM_CRIT("FIXME: null send_sock\n"); \ |
1158 | 0 | }; \ |
1159 | 0 | break; \ |
1160 | 0 | case SUBST_SND_ALL: \ |
1161 | 0 | case SUBST_SND_ALL_EX: \ |
1162 | 0 | if(send_sock) { \ |
1163 | | /* address */ \ |
1164 | 0 | if((send_sock->address.af == AF_INET6) \ |
1165 | 0 | && (send_address_str->s[0] != '[') \ |
1166 | 0 | && (memchr(send_address_str->s, ':', \ |
1167 | 0 | send_address_str->len) \ |
1168 | 0 | != NULL)) { \ |
1169 | 0 | new_buf[offset] = '['; \ |
1170 | 0 | offset++; \ |
1171 | 0 | } \ |
1172 | 0 | memcpy(new_buf + offset, send_address_str->s, \ |
1173 | 0 | send_address_str->len); \ |
1174 | 0 | offset += send_address_str->len; \ |
1175 | 0 | if((send_sock->address.af == AF_INET6) \ |
1176 | 0 | && (send_address_str->s[0] != '[') \ |
1177 | 0 | && (memchr(send_address_str->s, ':', \ |
1178 | 0 | send_address_str->len) \ |
1179 | 0 | != NULL)) { \ |
1180 | 0 | new_buf[offset] = ']'; \ |
1181 | 0 | offset++; \ |
1182 | 0 | } \ |
1183 | | /* :port */ \ |
1184 | 0 | if((send_sock->port_no != SIP_PORT) \ |
1185 | 0 | || (send_port_str != &(send_sock->port_no_str))) { \ |
1186 | 0 | new_buf[offset] = ':'; \ |
1187 | 0 | offset++; \ |
1188 | 0 | memcpy(new_buf + offset, send_port_str->s, \ |
1189 | 0 | send_port_str->len); \ |
1190 | 0 | offset += send_port_str->len; \ |
1191 | 0 | } \ |
1192 | 0 | switch(send_proto_id) { \ |
1193 | 0 | case PROTO_NONE: \ |
1194 | 0 | case PROTO_UDP: \ |
1195 | 0 | break; /* nothing to do, udp is default*/ \ |
1196 | 0 | case PROTO_TCP: \ |
1197 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1198 | 0 | TRANSPORT_PARAM_LEN); \ |
1199 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1200 | 0 | if(send_info->proto == PROTO_WS) { \ |
1201 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1202 | 0 | offset += 2; \ |
1203 | 0 | } else { \ |
1204 | 0 | memcpy(new_buf + offset, "tcp", 3); \ |
1205 | 0 | offset += 3; \ |
1206 | 0 | } \ |
1207 | 0 | break; \ |
1208 | 0 | case PROTO_TLS: \ |
1209 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1210 | 0 | TRANSPORT_PARAM_LEN); \ |
1211 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1212 | 0 | if(send_info->proto == PROTO_WS \ |
1213 | 0 | || send_info->proto == PROTO_WSS) { \ |
1214 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1215 | 0 | offset += 2; \ |
1216 | 0 | } else { \ |
1217 | 0 | memcpy(new_buf + offset, "tls", 3); \ |
1218 | 0 | offset += 3; \ |
1219 | 0 | } \ |
1220 | 0 | break; \ |
1221 | 0 | case PROTO_WS: \ |
1222 | 0 | case PROTO_WSS: \ |
1223 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1224 | 0 | TRANSPORT_PARAM_LEN); \ |
1225 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1226 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1227 | 0 | offset += 2; \ |
1228 | 0 | break; \ |
1229 | 0 | case PROTO_SCTP: \ |
1230 | 0 | memcpy(new_buf + offset, TRANSPORT_PARAM, \ |
1231 | 0 | TRANSPORT_PARAM_LEN); \ |
1232 | 0 | offset += TRANSPORT_PARAM_LEN; \ |
1233 | 0 | memcpy(new_buf + offset, "sctp", 4); \ |
1234 | 0 | offset += 4; \ |
1235 | 0 | break; \ |
1236 | 0 | default: \ |
1237 | 0 | LM_CRIT("unknown proto %d\n", send_sock->proto); \ |
1238 | 0 | } \ |
1239 | 0 | if((subst_l)->u.subst == SUBST_SND_ALL_EX \ |
1240 | 0 | && send_sock->sockname.len > 0) { \ |
1241 | 0 | memcpy(new_buf + offset, SOCKNAME_PARAM, \ |
1242 | 0 | SOCKNAME_PARAM_LEN); \ |
1243 | 0 | offset += SOCKNAME_PARAM_LEN; \ |
1244 | 0 | memcpy(new_buf + offset, send_sock->sockname.s, \ |
1245 | 0 | send_sock->sockname.len); \ |
1246 | 0 | offset += send_sock->sockname.len; \ |
1247 | 0 | } \ |
1248 | 0 | SENDCOMP_PARAM_ADD \ |
1249 | 0 | } else { \ |
1250 | | /*FIXME*/ \ |
1251 | 0 | LM_CRIT("FIXME: null bind_address\n"); \ |
1252 | 0 | }; \ |
1253 | 0 | break; \ |
1254 | 0 | case SUBST_RCV_PROTO: \ |
1255 | 0 | if(msg->rcv.bind_address) { \ |
1256 | 0 | switch(msg->rcv.bind_address->proto) { \ |
1257 | 0 | case PROTO_NONE: \ |
1258 | 0 | case PROTO_UDP: \ |
1259 | 0 | memcpy(new_buf + offset, "udp", 3); \ |
1260 | 0 | offset += 3; \ |
1261 | 0 | break; \ |
1262 | 0 | case PROTO_TCP: \ |
1263 | 0 | if(msg->rcv.proto == PROTO_WS) { \ |
1264 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1265 | 0 | offset += 2; \ |
1266 | 0 | } else { \ |
1267 | 0 | memcpy(new_buf + offset, "tcp", 3); \ |
1268 | 0 | offset += 3; \ |
1269 | 0 | } \ |
1270 | 0 | break; \ |
1271 | 0 | case PROTO_TLS: \ |
1272 | 0 | if(msg->rcv.proto == PROTO_WS \ |
1273 | 0 | || msg->rcv.proto == PROTO_WSS) { \ |
1274 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1275 | 0 | offset += 2; \ |
1276 | 0 | } else { \ |
1277 | 0 | memcpy(new_buf + offset, "tls", 3); \ |
1278 | 0 | offset += 3; \ |
1279 | 0 | } \ |
1280 | 0 | break; \ |
1281 | 0 | case PROTO_SCTP: \ |
1282 | 0 | memcpy(new_buf + offset, "sctp", 4); \ |
1283 | 0 | offset += 4; \ |
1284 | 0 | break; \ |
1285 | 0 | default: \ |
1286 | 0 | LM_CRIT("unknown proto %d\n", \ |
1287 | 0 | msg->rcv.bind_address->proto); \ |
1288 | 0 | } \ |
1289 | 0 | } else { \ |
1290 | | /*FIXME*/ \ |
1291 | 0 | LM_CRIT("FIXME: null send_sock \n"); \ |
1292 | 0 | }; \ |
1293 | 0 | break; \ |
1294 | 0 | case SUBST_SND_PROTO: \ |
1295 | 0 | if(send_sock) { \ |
1296 | 0 | switch(send_sock->proto) { \ |
1297 | 0 | case PROTO_NONE: \ |
1298 | 0 | case PROTO_UDP: \ |
1299 | 0 | memcpy(new_buf + offset, "udp", 3); \ |
1300 | 0 | offset += 3; \ |
1301 | 0 | break; \ |
1302 | 0 | case PROTO_TCP: \ |
1303 | 0 | if(send_info->proto == PROTO_WS) { \ |
1304 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1305 | 0 | offset += 2; \ |
1306 | 0 | } else { \ |
1307 | 0 | memcpy(new_buf + offset, "tcp", 3); \ |
1308 | 0 | offset += 3; \ |
1309 | 0 | } \ |
1310 | 0 | break; \ |
1311 | 0 | case PROTO_TLS: \ |
1312 | 0 | if(send_info->proto == PROTO_WS \ |
1313 | 0 | || send_info->proto == PROTO_WSS) { \ |
1314 | 0 | memcpy(new_buf + offset, "ws", 2); \ |
1315 | 0 | offset += 2; \ |
1316 | 0 | } else { \ |
1317 | 0 | memcpy(new_buf + offset, "tls", 3); \ |
1318 | 0 | offset += 3; \ |
1319 | 0 | } \ |
1320 | 0 | break; \ |
1321 | 0 | case PROTO_SCTP: \ |
1322 | 0 | memcpy(new_buf + offset, "sctp", 4); \ |
1323 | 0 | offset += 4; \ |
1324 | 0 | break; \ |
1325 | 0 | default: \ |
1326 | 0 | LM_CRIT("unknown proto %d\n", send_sock->proto); \ |
1327 | 0 | } \ |
1328 | 0 | } else { \ |
1329 | | /*FIXME*/ \ |
1330 | 0 | LM_CRIT("FIXME: null send_sock \n"); \ |
1331 | 0 | }; \ |
1332 | 0 | break; \ |
1333 | 0 | default: \ |
1334 | 0 | LM_CRIT("unknown subst type %d\n", (subst_l)->u.subst); \ |
1335 | 0 | } |
1336 | |
|
1337 | 0 | if(send_info) { |
1338 | 0 | send_sock = send_info->send_sock; |
1339 | 0 | } else { |
1340 | 0 | send_sock = 0; |
1341 | 0 | } |
1342 | | /* init send_address_str & send_port_str */ |
1343 | 0 | if(msg->set_global_address.len) |
1344 | 0 | send_address_str = &(msg->set_global_address); |
1345 | 0 | else |
1346 | 0 | send_address_str = &(send_sock->address_str); |
1347 | 0 | if(msg->set_global_port.len) |
1348 | 0 | send_port_str = &(msg->set_global_port); |
1349 | 0 | else |
1350 | 0 | send_port_str = &(send_sock->port_no_str); |
1351 | | /* init send_address_str & send_port_str */ |
1352 | 0 | if(send_sock && send_sock->useinfo.name.len > 0) |
1353 | 0 | send_address_str = &(send_sock->useinfo.name); |
1354 | 0 | else if(msg->set_global_address.len) |
1355 | 0 | send_address_str = &(msg->set_global_address); |
1356 | 0 | else |
1357 | 0 | send_address_str = &(send_sock->address_str); |
1358 | 0 | if(send_sock && send_sock->useinfo.port_no > 0) |
1359 | 0 | send_port_str = &(send_sock->useinfo.port_no_str); |
1360 | 0 | else if(msg->set_global_port.len) |
1361 | 0 | send_port_str = &(msg->set_global_port); |
1362 | 0 | else |
1363 | 0 | send_port_str = &(send_sock->port_no_str); |
1364 | 0 | if(send_sock) { |
1365 | 0 | if(send_sock->useinfo.proto != PROTO_NONE) |
1366 | 0 | send_proto_id = send_sock->useinfo.proto; |
1367 | 0 | else |
1368 | 0 | send_proto_id = send_sock->proto; |
1369 | 0 | } |
1370 | | /* init recv_address_str, recv_port_str & recv_port_no */ |
1371 | 0 | if(msg->rcv.bind_address) { |
1372 | 0 | if(msg->rcv.bind_address->useinfo.name.len > 0) |
1373 | 0 | recv_address_str = &(msg->rcv.bind_address->useinfo.name); |
1374 | 0 | else |
1375 | 0 | recv_address_str = &(msg->rcv.bind_address->address_str); |
1376 | 0 | if(msg->rcv.bind_address->useinfo.port_no > 0) { |
1377 | 0 | recv_port_str = &(msg->rcv.bind_address->useinfo.port_no_str); |
1378 | 0 | recv_port_no = msg->rcv.bind_address->useinfo.port_no; |
1379 | 0 | } else { |
1380 | 0 | recv_port_str = &(msg->rcv.bind_address->port_no_str); |
1381 | 0 | recv_port_no = msg->rcv.bind_address->port_no; |
1382 | 0 | } |
1383 | 0 | if(msg->rcv.bind_address->useinfo.proto != PROTO_NONE) { |
1384 | 0 | recv_proto_id = msg->rcv.bind_address->useinfo.proto; |
1385 | 0 | } else { |
1386 | 0 | recv_proto_id = msg->rcv.bind_address->proto; |
1387 | 0 | } |
1388 | 0 | } |
1389 | |
|
1390 | 0 | orig = msg->buf; |
1391 | 0 | offset = *new_buf_offs; |
1392 | 0 | s_offset = *orig_offs; |
1393 | |
|
1394 | 0 | for(t = lumps; t; t = t->next) { |
1395 | 0 | switch(t->op) { |
1396 | 0 | case LUMP_ADD: |
1397 | 0 | case LUMP_ADD_SUBST: |
1398 | 0 | case LUMP_ADD_OPT: |
1399 | | /* skip if this is an OPT lump and the condition is |
1400 | | * not satisfied */ |
1401 | 0 | if((t->op == LUMP_ADD_OPT) |
1402 | 0 | && (!lump_check_opt(t, msg, send_info))) |
1403 | 0 | continue; |
1404 | | /* just add it here! */ |
1405 | | /* process before */ |
1406 | 0 | for(r = t->before; r; r = r->before) { |
1407 | 0 | switch(r->op) { |
1408 | 0 | case LUMP_ADD: |
1409 | | /*just add it here*/ |
1410 | 0 | memcpy(new_buf + offset, r->u.value, r->len); |
1411 | 0 | offset += r->len; |
1412 | 0 | break; |
1413 | 0 | case LUMP_ADD_SUBST: |
1414 | 0 | SUBST_LUMP(r); |
1415 | 0 | break; |
1416 | 0 | case LUMP_ADD_OPT: |
1417 | | /* skip if this is an OPT lump and the condition is |
1418 | | * not satisfied */ |
1419 | 0 | if(!lump_check_opt(r, msg, send_info)) |
1420 | 0 | goto skip_before; |
1421 | 0 | break; |
1422 | 0 | default: |
1423 | | /* only ADD allowed for before/after */ |
1424 | 0 | LM_CRIT("invalid op for data lump (%x)\n", r->op); |
1425 | 0 | } |
1426 | 0 | } |
1427 | 0 | skip_before: |
1428 | | /* copy "main" part */ |
1429 | 0 | switch(t->op) { |
1430 | 0 | case LUMP_ADD: |
1431 | 0 | memcpy(new_buf + offset, t->u.value, t->len); |
1432 | 0 | offset += t->len; |
1433 | 0 | break; |
1434 | 0 | case LUMP_ADD_SUBST: |
1435 | 0 | SUBST_LUMP(t); |
1436 | 0 | break; |
1437 | 0 | case LUMP_ADD_OPT: |
1438 | | /* do nothing, it's only a condition */ |
1439 | 0 | break; |
1440 | 0 | default: |
1441 | | /* should not ever get here */ |
1442 | 0 | LM_CRIT("unhandled data lump op %d\n", t->op); |
1443 | 0 | } |
1444 | | /* process after */ |
1445 | 0 | for(r = t->after; r; r = r->after) { |
1446 | 0 | switch(r->op) { |
1447 | 0 | case LUMP_ADD: |
1448 | | /*just add it here*/ |
1449 | 0 | memcpy(new_buf + offset, r->u.value, r->len); |
1450 | 0 | offset += r->len; |
1451 | 0 | break; |
1452 | 0 | case LUMP_ADD_SUBST: |
1453 | 0 | SUBST_LUMP(r); |
1454 | 0 | break; |
1455 | 0 | case LUMP_ADD_OPT: |
1456 | | /* skip if this is an OPT lump and the condition is |
1457 | | * not satisfied */ |
1458 | 0 | if(!lump_check_opt(r, msg, send_info)) |
1459 | 0 | goto skip_after; |
1460 | 0 | break; |
1461 | 0 | default: |
1462 | | /* only ADD allowed for before/after */ |
1463 | 0 | LM_CRIT("invalid op for data lump (%x)\n", r->op); |
1464 | 0 | } |
1465 | 0 | } |
1466 | 0 | skip_after: |
1467 | 0 | break; |
1468 | 0 | case LUMP_NOP: |
1469 | 0 | case LUMP_DEL: |
1470 | | /* copy till offset */ |
1471 | 0 | if(s_offset > t->u.offset) { |
1472 | 0 | LM_DBG("WARNING: (%d) overlapped lumps offsets," |
1473 | 0 | " ignoring(%x, %x)\n", |
1474 | 0 | t->op, s_offset, t->u.offset); |
1475 | | /* this should've been fixed above (when computing len) */ |
1476 | | /* just ignore it*/ |
1477 | 0 | break; |
1478 | 0 | } |
1479 | 0 | size = t->u.offset - s_offset; |
1480 | 0 | if(size > 0 && flag == FLAG_MSG_ALL) { |
1481 | 0 | memcpy(new_buf + offset, orig + s_offset, size); |
1482 | 0 | offset += size; |
1483 | 0 | s_offset += size; |
1484 | 0 | } else if(flag == FLAG_MSG_LUMPS_ONLY) { |
1485 | | /* do not copy the whole message, jump to the lumps offs */ |
1486 | 0 | s_offset += size; |
1487 | 0 | } |
1488 | | |
1489 | | /* the LUMP_DELs are printed with "- " before them */ |
1490 | 0 | if(t->op == LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) { |
1491 | 0 | new_buf[offset++] = '-'; |
1492 | 0 | new_buf[offset++] = ' '; |
1493 | 0 | } |
1494 | | |
1495 | | /* process before */ |
1496 | 0 | for(r = t->before; r; r = r->before) { |
1497 | 0 | switch(r->op) { |
1498 | 0 | case LUMP_ADD: |
1499 | | /*just add it here*/ |
1500 | 0 | memcpy(new_buf + offset, r->u.value, r->len); |
1501 | 0 | offset += r->len; |
1502 | 0 | break; |
1503 | 0 | case LUMP_ADD_SUBST: |
1504 | 0 | SUBST_LUMP(r); |
1505 | 0 | break; |
1506 | 0 | case LUMP_ADD_OPT: |
1507 | | /* skip if this is an OPT lump and the condition is |
1508 | | * not satisfied */ |
1509 | 0 | if(!lump_check_opt(r, msg, send_info)) |
1510 | 0 | goto skip_nop_before; |
1511 | 0 | break; |
1512 | 0 | default: |
1513 | | /* only ADD allowed for before/after */ |
1514 | 0 | LM_CRIT("invalid op for data lump (%x)\n", r->op); |
1515 | 0 | } |
1516 | 0 | } |
1517 | 0 | skip_nop_before: |
1518 | | /* process main (del only) */ |
1519 | 0 | if(t->op == LUMP_DEL && flag == FLAG_MSG_ALL) { |
1520 | | /* skip len bytes from orig msg */ |
1521 | 0 | s_offset += t->len; |
1522 | 0 | } else if(t->op == LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) { |
1523 | | /* copy lump value and indent as necessarily */ |
1524 | 0 | memcpy(new_buf + offset, orig + t->u.offset, t->len); |
1525 | 0 | offset += t->len; |
1526 | 0 | if(new_buf[offset - 1] != '\n') { |
1527 | 0 | new_buf[offset] = '\n'; |
1528 | 0 | offset += 1; |
1529 | 0 | } |
1530 | | /* skip len bytes from orig msg */ |
1531 | 0 | s_offset += t->len; |
1532 | 0 | } |
1533 | | |
1534 | | /* process after */ |
1535 | 0 | for(r = t->after; r; r = r->after) { |
1536 | 0 | switch(r->op) { |
1537 | 0 | case LUMP_ADD: |
1538 | | /*just add it here*/ |
1539 | 0 | memcpy(new_buf + offset, r->u.value, r->len); |
1540 | 0 | offset += r->len; |
1541 | 0 | break; |
1542 | 0 | case LUMP_ADD_SUBST: |
1543 | 0 | SUBST_LUMP(r); |
1544 | 0 | break; |
1545 | 0 | case LUMP_ADD_OPT: |
1546 | | /* skip if this is an OPT lump and the condition is |
1547 | | * not satisfied */ |
1548 | 0 | if(!lump_check_opt(r, msg, send_info)) |
1549 | 0 | goto skip_nop_after; |
1550 | 0 | break; |
1551 | 0 | default: |
1552 | | /* only ADD allowed for before/after */ |
1553 | 0 | LM_CRIT("invalid op for data lump (%x)\n", r->op); |
1554 | 0 | } |
1555 | 0 | } |
1556 | 0 | skip_nop_after: |
1557 | 0 | break; |
1558 | 0 | default: |
1559 | 0 | LM_CRIT("unknown op (%x)\n", t->op); |
1560 | 0 | } |
1561 | 0 | } |
1562 | 0 | *new_buf_offs = offset; |
1563 | 0 | *orig_offs = s_offset; |
1564 | | |
1565 | | /* add '\0' to char* lump list to print it smoothly */ |
1566 | 0 | if(flag == FLAG_MSG_LUMPS_ONLY) { |
1567 | 0 | new_buf[offset] = '\0'; |
1568 | 0 | } |
1569 | 0 | #undef RCVCOMP_PARAM_ADD |
1570 | 0 | #undef SENDCOMP_PARAM_ADD |
1571 | 0 | } |
1572 | | |
1573 | | |
1574 | | /* |
1575 | | * Adjust/insert Content-Length if necessary |
1576 | | */ |
1577 | | static inline int adjust_clen(struct sip_msg *msg, int body_delta, int proto) |
1578 | 0 | { |
1579 | 0 | struct lump *anchor; |
1580 | 0 | char *clen_buf; |
1581 | 0 | int clen_len, body_only; |
1582 | 0 | #ifdef USE_TCP |
1583 | 0 | char *body; |
1584 | 0 | int comp_clen; |
1585 | 0 | #endif /* USE_TCP */ |
1586 | | |
1587 | | /* Calculate message length difference caused by lumps modifying message |
1588 | | * body, from this point on the message body must not be modified. Zero |
1589 | | * value indicates that the body hasn't been modified |
1590 | | */ |
1591 | |
|
1592 | 0 | clen_buf = 0; |
1593 | 0 | anchor = 0; |
1594 | 0 | body_only = 1; |
1595 | | |
1596 | | /* check to see if we need to add clen */ |
1597 | 0 | #ifdef USE_TCP |
1598 | 0 | if(proto == PROTO_TCP |
1599 | 0 | #ifdef USE_TLS |
1600 | 0 | || proto == PROTO_TLS |
1601 | 0 | #endif |
1602 | 0 | ) { |
1603 | 0 | if(parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) { |
1604 | 0 | LM_ERR("error parsing content-length\n"); |
1605 | 0 | goto error; |
1606 | 0 | } |
1607 | 0 | if(unlikely(msg->content_length == 0)) { |
1608 | | /* not present, we need to add it */ |
1609 | | /* msg->unparsed should point just before the final crlf |
1610 | | * - whole message was parsed by the above parse_headers |
1611 | | * which did not find content-length */ |
1612 | 0 | anchor = anchor_lump( |
1613 | 0 | msg, msg->unparsed - msg->buf, 0, HDR_CONTENTLENGTH_T); |
1614 | 0 | if(anchor == 0) { |
1615 | 0 | LM_ERR("cannot set clen anchor\n"); |
1616 | 0 | goto error; |
1617 | 0 | } |
1618 | 0 | body_only = 0; |
1619 | 0 | } else { |
1620 | | /* compute current content length and compare it with the |
1621 | | one in the message */ |
1622 | 0 | body = get_body(msg); |
1623 | 0 | if(unlikely(body == 0)) { |
1624 | 0 | ser_error = E_BAD_REQ; |
1625 | 0 | LM_ERR("no message body found (missing crlf?)"); |
1626 | 0 | goto error; |
1627 | 0 | } |
1628 | 0 | comp_clen = msg->len - (int)(body - msg->buf) + body_delta; |
1629 | 0 | if(comp_clen != (int)(long)msg->content_length->parsed) { |
1630 | | /* note: we don't distinguish here between received with |
1631 | | wrong content-length and content-length changed, we just |
1632 | | fix it automatically in both cases (the reason being |
1633 | | that an error message telling we have received a msg- |
1634 | | with wrong content-length is of very little use) */ |
1635 | 0 | anchor = del_lump(msg, msg->content_length->body.s - msg->buf, |
1636 | 0 | msg->content_length->body.len, HDR_CONTENTLENGTH_T); |
1637 | 0 | if(anchor == 0) { |
1638 | 0 | LM_ERR("Can't remove original Content-Length\n"); |
1639 | 0 | goto error; |
1640 | 0 | } |
1641 | 0 | body_only = 1; |
1642 | 0 | } |
1643 | 0 | } |
1644 | 0 | } else |
1645 | 0 | #endif /* USE_TCP */ |
1646 | 0 | if(body_delta) { |
1647 | 0 | if(parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) { |
1648 | 0 | LM_ERR("Error parsing Content-Length\n"); |
1649 | 0 | goto error; |
1650 | 0 | } |
1651 | | |
1652 | | /* The body has been changed, try to find |
1653 | | * existing Content-Length |
1654 | | */ |
1655 | | /* no need for Content-Length if it's an UDP packet and |
1656 | | * it hasn't Content-Length already */ |
1657 | 0 | if(msg->content_length == 0) { |
1658 | | /* content-length doesn't exist, append it */ |
1659 | | /* msg->unparsed should point just before the final crlf |
1660 | | * - whole message was parsed by the above parse_headers |
1661 | | * which did not find content-length */ |
1662 | 0 | if(proto != PROTO_UDP) { |
1663 | 0 | anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, |
1664 | 0 | HDR_CONTENTLENGTH_T); |
1665 | 0 | if(anchor == 0) { |
1666 | 0 | LM_ERR("cannot set clen anchor\n"); |
1667 | 0 | goto error; |
1668 | 0 | } |
1669 | 0 | body_only = 0; |
1670 | 0 | } /* else |
1671 | | LM_DBG("UDP packet with no clen => not adding one \n"); */ |
1672 | 0 | } else { |
1673 | | /* Content-Length has been found, remove it */ |
1674 | 0 | anchor = del_lump(msg, msg->content_length->body.s - msg->buf, |
1675 | 0 | msg->content_length->body.len, HDR_CONTENTLENGTH_T); |
1676 | 0 | if(anchor == 0) { |
1677 | 0 | LM_ERR("Can't remove original Content-Length\n"); |
1678 | 0 | goto error; |
1679 | 0 | } |
1680 | 0 | } |
1681 | 0 | } |
1682 | | |
1683 | 0 | if(anchor) { |
1684 | 0 | clen_buf = clen_builder(msg, &clen_len, body_delta, body_only); |
1685 | 0 | if(!clen_buf) |
1686 | 0 | goto error; |
1687 | 0 | if(insert_new_lump_after( |
1688 | 0 | anchor, clen_buf, clen_len, HDR_CONTENTLENGTH_T) |
1689 | 0 | == 0) |
1690 | 0 | goto error; |
1691 | 0 | } |
1692 | | |
1693 | 0 | return 0; |
1694 | 0 | error: |
1695 | 0 | if(clen_buf) |
1696 | 0 | pkg_free(clen_buf); |
1697 | 0 | return -1; |
1698 | 0 | } |
1699 | | |
1700 | | static inline int find_line_start( |
1701 | | char *text, unsigned int text_len, char **buf, unsigned int *buf_len) |
1702 | 0 | { |
1703 | 0 | char *ch, *start; |
1704 | 0 | unsigned int len; |
1705 | |
|
1706 | 0 | start = *buf; |
1707 | 0 | len = *buf_len; |
1708 | |
|
1709 | 0 | while(text_len <= len) { |
1710 | 0 | if(strncmp(text, start, text_len) == 0) { |
1711 | 0 | *buf = start; |
1712 | 0 | *buf_len = len; |
1713 | 0 | return 1; |
1714 | 0 | } |
1715 | 0 | if((ch = memchr(start, 13, len - 1))) { |
1716 | 0 | if(*(ch + 1) != 10) { |
1717 | 0 | LM_ERR("No LF after CR\n"); |
1718 | 0 | return 0; |
1719 | 0 | } |
1720 | 0 | len = len - (ch - start + 2); |
1721 | 0 | start = ch + 2; |
1722 | 0 | } else { |
1723 | 0 | LM_ERR("No CRLF found\n"); |
1724 | 0 | return 0; |
1725 | 0 | } |
1726 | 0 | } |
1727 | 0 | return 0; |
1728 | 0 | } |
1729 | | |
1730 | | static inline int get_line(str s) |
1731 | 0 | { |
1732 | 0 | char *ch; |
1733 | |
|
1734 | 0 | if((ch = memchr(s.s, 13, s.len))) { |
1735 | 0 | if(*(ch + 1) != 10) { |
1736 | 0 | LM_ERR("No LF after CR\n"); |
1737 | 0 | return 0; |
1738 | 0 | } |
1739 | 0 | return ch - s.s + 2; |
1740 | 0 | } else { |
1741 | 0 | LM_ERR("No CRLF found\n"); |
1742 | 0 | return s.len; |
1743 | 0 | } |
1744 | 0 | return 0; |
1745 | 0 | } |
1746 | | |
1747 | | int replace_body(struct sip_msg *msg, str txt) |
1748 | 0 | { |
1749 | 0 | struct lump *anchor; |
1750 | 0 | char *buf; |
1751 | 0 | str body = {0, 0}; |
1752 | |
|
1753 | 0 | body.s = get_body(msg); |
1754 | 0 | if(body.s == 0) { |
1755 | 0 | LM_ERR("malformed sip message\n"); |
1756 | 0 | return 0; |
1757 | 0 | } |
1758 | 0 | body.len = msg->len - (int)(body.s - msg->buf); |
1759 | 0 | LM_DBG("old size body[%d] actual[%d]\n", body.len, txt.len); |
1760 | 0 | if(body.s + body.len > msg->buf + msg->len) { |
1761 | 0 | LM_ERR("invalid content length: %d\n", body.len); |
1762 | 0 | return 0; |
1763 | 0 | } |
1764 | 0 | del_nonshm_lump(&(msg->body_lumps)); |
1765 | 0 | msg->body_lumps = NULL; |
1766 | |
|
1767 | 0 | if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0) { |
1768 | 0 | LM_ERR("cannot delete existing body"); |
1769 | 0 | return 0; |
1770 | 0 | } |
1771 | | |
1772 | 0 | anchor = anchor_lump(msg, body.s - msg->buf, 0, 0); |
1773 | 0 | if(anchor == 0) { |
1774 | 0 | LM_ERR("failed to get anchor\n"); |
1775 | 0 | return 0; |
1776 | 0 | } |
1777 | | |
1778 | 0 | buf = pkg_malloc(sizeof(char) * txt.len); |
1779 | 0 | if(buf == 0) { |
1780 | 0 | PKG_MEM_ERROR; |
1781 | 0 | return 0; |
1782 | 0 | } |
1783 | 0 | memcpy(buf, txt.s, txt.len); |
1784 | 0 | if(insert_new_lump_after(anchor, buf, txt.len, 0) == 0) { |
1785 | 0 | LM_ERR("failed to insert body lump\n"); |
1786 | 0 | pkg_free(buf); |
1787 | 0 | return 0; |
1788 | 0 | } |
1789 | 0 | return 1; |
1790 | 0 | } |
1791 | | |
1792 | | /** |
1793 | | * returns the boundary defined by the Content-Type |
1794 | | * header |
1795 | | */ |
1796 | | int get_boundary(struct sip_msg *msg, str *boundary) |
1797 | 0 | { |
1798 | 0 | str params; |
1799 | 0 | param_t *p, *list; |
1800 | 0 | param_hooks_t hooks; |
1801 | |
|
1802 | 0 | params.s = |
1803 | 0 | memchr(msg->content_type->body.s, ';', msg->content_type->body.len); |
1804 | 0 | if(params.s == NULL) { |
1805 | 0 | LM_INFO("Content-Type hdr has no boundary params <%.*s>\n", |
1806 | 0 | msg->content_type->body.len, msg->content_type->body.s); |
1807 | 0 | return -2; |
1808 | 0 | } |
1809 | 0 | params.len = msg->content_type->body.len |
1810 | 0 | - (params.s - msg->content_type->body.s); |
1811 | 0 | if(parse_params(¶ms, CLASS_ANY, &hooks, &list) < 0) { |
1812 | 0 | LM_ERR("while parsing Content-Type params\n"); |
1813 | 0 | return -1; |
1814 | 0 | } |
1815 | 0 | boundary->s = NULL; |
1816 | 0 | boundary->len = 0; |
1817 | 0 | for(p = list; p; p = p->next) { |
1818 | 0 | if((p->name.len == 8) && (strncasecmp(p->name.s, "boundary", 8) == 0)) { |
1819 | 0 | boundary->s = pkg_malloc(p->body.len + 2); |
1820 | 0 | if(boundary->s == NULL) { |
1821 | 0 | free_params(list); |
1822 | 0 | PKG_MEM_ERROR; |
1823 | 0 | return -1; |
1824 | 0 | } |
1825 | 0 | *(boundary->s) = '-'; |
1826 | 0 | *(boundary->s + 1) = '-'; |
1827 | 0 | memcpy(boundary->s + 2, p->body.s, p->body.len); |
1828 | 0 | boundary->len = 2 + p->body.len; |
1829 | 0 | LM_DBG("boundary is <%.*s>\n", boundary->len, boundary->s); |
1830 | 0 | break; |
1831 | 0 | } |
1832 | 0 | } |
1833 | 0 | free_params(list); |
1834 | 0 | return 0; |
1835 | 0 | } |
1836 | | |
1837 | | int check_boundaries(struct sip_msg *msg, struct dest_info *send_info) |
1838 | 0 | { |
1839 | 0 | str b = {0, 0}; |
1840 | 0 | str fb = {0, 0}; |
1841 | 0 | str ob = {0, 0}; |
1842 | 0 | str bsuffix = {"\r\n", 2}; |
1843 | 0 | str fsuffix = {"--\r\n", 4}; |
1844 | 0 | str body = {0, 0}; |
1845 | 0 | str buf = {0, 0}; |
1846 | 0 | str tmp = {0, 0}; |
1847 | 0 | struct str_list *lb = NULL; |
1848 | 0 | struct str_list *lb_t = NULL; |
1849 | 0 | int lb_found = 0; |
1850 | 0 | int t, ret, lb_size; |
1851 | 0 | char *pb; |
1852 | |
|
1853 | 0 | if(!(msg->msg_flags & FL_BODY_MULTIPART)) { |
1854 | 0 | LM_DBG("no multi-part body\n"); |
1855 | 0 | return 0; |
1856 | 0 | } else { |
1857 | 0 | if((t = get_boundary(msg, &ob)) != 0) { |
1858 | 0 | if(t == -2) { |
1859 | 0 | LM_INFO("no boundary - maybe just turning into multipart " |
1860 | 0 | "body\n"); |
1861 | 0 | return -2; |
1862 | 0 | } |
1863 | 0 | return -1; |
1864 | 0 | } |
1865 | 0 | buf.s = build_body(msg, (unsigned int *)&buf.len, &ret, send_info); |
1866 | 0 | if(ret) { |
1867 | 0 | LM_ERR("Can't get body\n"); |
1868 | 0 | return -1; |
1869 | 0 | } |
1870 | 0 | tmp.s = buf.s; |
1871 | 0 | t = tmp.len = buf.len; |
1872 | 0 | if(str_append(&ob, &bsuffix, &b) != 0) { |
1873 | 0 | LM_ERR("Can't append suffix to boundary\n"); |
1874 | 0 | goto error; |
1875 | 0 | } |
1876 | 0 | if(str_append(&ob, &fsuffix, &fb) != 0) { |
1877 | 0 | LM_ERR("Can't append suffix to final boundary\n"); |
1878 | 0 | goto error; |
1879 | 0 | } |
1880 | 0 | ret = b.len - 2; |
1881 | 0 | while(t > 0) { |
1882 | 0 | if(find_line_start(b.s, ret, &tmp.s, (unsigned int *)&tmp.len)) { |
1883 | | /*LM_DBG("found t[%d] tmp.len[%d]:[%.*s]\n", |
1884 | | t, tmp.len, tmp.len, tmp.s);*/ |
1885 | 0 | if(!lb) { |
1886 | 0 | lb = pkg_malloc(sizeof(struct str_list)); |
1887 | 0 | if(!lb) { |
1888 | 0 | PKG_MEM_ERROR; |
1889 | 0 | goto error; |
1890 | 0 | } |
1891 | 0 | lb->s.s = tmp.s; |
1892 | 0 | lb->s.len = tmp.len; |
1893 | 0 | lb->next = 0; |
1894 | 0 | lb_t = lb; |
1895 | 0 | } else { |
1896 | 0 | lb_t = append_str_list(tmp.s, tmp.len, &lb_t, &lb_size); |
1897 | 0 | } |
1898 | 0 | lb_found = lb_found + 1; |
1899 | 0 | tmp.s = tmp.s + ret; |
1900 | 0 | t = t - ret; |
1901 | 0 | tmp.len = tmp.len - ret; |
1902 | 0 | } else { |
1903 | 0 | t = 0; |
1904 | 0 | } |
1905 | 0 | } |
1906 | 0 | if(lb_found < 2) { |
1907 | 0 | LM_ERR("found[%d] wrong number of boundaries\n", lb_found); |
1908 | 0 | goto error; |
1909 | 0 | } |
1910 | | /* adding 2 chars in advance */ |
1911 | 0 | body.len = buf.len + 2; |
1912 | 0 | body.s = pkg_malloc(sizeof(char) * body.len); |
1913 | 0 | if(!body.s) { |
1914 | 0 | PKG_MEM_ERROR; |
1915 | 0 | goto error; |
1916 | 0 | } |
1917 | 0 | pb = body.s; |
1918 | 0 | body.len = 0; |
1919 | 0 | lb_t = lb; |
1920 | 0 | while(lb_t) { |
1921 | 0 | tmp.s = lb_t->s.s; |
1922 | 0 | tmp.len = lb_t->s.len; |
1923 | 0 | tmp.len = get_line(lb_t->s); |
1924 | 0 | if(tmp.len != b.len || strncmp(b.s, tmp.s, b.len) != 0) { |
1925 | 0 | LM_DBG("malformed boundary in the middle\n"); |
1926 | 0 | memcpy(pb, b.s, b.len); |
1927 | 0 | body.len = body.len + b.len; |
1928 | 0 | pb = pb + b.len; |
1929 | 0 | t = lb_t->next->s.s - (lb_t->s.s + tmp.len); |
1930 | 0 | memcpy(pb, lb_t->s.s + tmp.len, t); |
1931 | 0 | pb = pb + t; |
1932 | | /*LM_DBG("new chunk[%d][%.*s]\n", t, t, pb-t);*/ |
1933 | 0 | } else { |
1934 | 0 | t = lb_t->next->s.s - lb_t->s.s; |
1935 | 0 | memcpy(pb, lb_t->s.s, t); |
1936 | | /*LM_DBG("copy[%d][%.*s]\n", t, t, pb);*/ |
1937 | 0 | pb = pb + t; |
1938 | 0 | } |
1939 | 0 | body.len = body.len + t; |
1940 | | /*LM_DBG("body[%d][%.*s]\n", body.len, body.len, body.s);*/ |
1941 | 0 | lb_t = lb_t->next; |
1942 | 0 | if(!lb_t->next) |
1943 | 0 | lb_t = NULL; |
1944 | 0 | } |
1945 | | /* last boundary */ |
1946 | 0 | tmp.s = lb->s.s; |
1947 | 0 | tmp.len = lb->s.len; |
1948 | 0 | tmp.len = get_line(lb->s); |
1949 | 0 | if(tmp.len != fb.len || strncmp(fb.s, tmp.s, fb.len) != 0) { |
1950 | 0 | LM_DBG("last bondary without -- at the end\n"); |
1951 | 0 | memcpy(pb, fb.s, fb.len); |
1952 | | /*LM_DBG("new chunk[%d][%.*s]\n", fb.len, fb.len, pb);*/ |
1953 | 0 | pb = pb + fb.len; |
1954 | 0 | body.len = body.len + fb.len; |
1955 | 0 | } else { |
1956 | 0 | memcpy(pb, lb->s.s, lb->s.len); |
1957 | 0 | pb = pb + lb->s.len; |
1958 | 0 | body.len = body.len + lb->s.len; |
1959 | | /*LM_DBG("copy[%d][%.*s]\n", lb->s.len, lb->s.len, pb - lb->s.len);*/ |
1960 | 0 | } |
1961 | | /*LM_DBG("body[%d][%.*s] expected[%ld]\n", |
1962 | | body.len, body.len, body.s, pb-body.s); */ |
1963 | 0 | if(!replace_body(msg, body)) { |
1964 | 0 | LM_ERR("Can't replace body\n"); |
1965 | 0 | goto error; |
1966 | 0 | } |
1967 | 0 | msg->msg_flags &= ~FL_BODY_MULTIPART; |
1968 | 0 | ret = 1; |
1969 | 0 | goto clean; |
1970 | 0 | } |
1971 | | |
1972 | 0 | error: |
1973 | 0 | ret = -1; |
1974 | 0 | clean: |
1975 | 0 | if(ob.s) |
1976 | 0 | pkg_free(ob.s); |
1977 | 0 | if(b.s) |
1978 | 0 | pkg_free(b.s); |
1979 | 0 | if(fb.s) |
1980 | 0 | pkg_free(fb.s); |
1981 | 0 | if(body.s) |
1982 | 0 | pkg_free(body.s); |
1983 | 0 | if(buf.s) |
1984 | 0 | pkg_free(buf.s); |
1985 | 0 | while(lb) { |
1986 | 0 | lb_t = lb->next; |
1987 | 0 | pkg_free(lb); |
1988 | 0 | lb = lb_t; |
1989 | 0 | } |
1990 | 0 | return ret; |
1991 | 0 | } |
1992 | | |
1993 | | /** builds a request in memory from another sip request. |
1994 | | * |
1995 | | * Side-effects: - it adds lumps to the msg which are _not_ cleaned. |
1996 | | * The added lumps are HDR_VIA_T (almost always added), HDR_CONTENTLENGTH_T |
1997 | | * and HDR_ROUTE_T (when a Route: header is added as a result of a non-null |
1998 | | * msg->path_vec). |
1999 | | * - it might change send_info->proto and send_info->send_socket |
2000 | | * if proto fallback is enabled (see below). |
2001 | | * |
2002 | | * Uses also global_req_flags ( OR'ed with msg->msg_flags, see send_info |
2003 | | * below). |
2004 | | * |
2005 | | * @param msg - sip message structure, complete with lumps |
2006 | | * @param returned_len - result length (filled in) |
2007 | | * @param send_info - dest_info structure (value/result), contains where the |
2008 | | * packet will be sent to (it's needed for building a |
2009 | | * correct via, fill RR lumps a.s.o.). If MTU based |
2010 | | * protocol fall-back is enabled (see flags below), |
2011 | | * send_info->proto might be updated with the new |
2012 | | * protocol. |
2013 | | * msg->msg_flags used: |
2014 | | * - FL_TCP_MTU_FB, FL_TLS_MTU_FB and FL_SCTP_MTU_FB - |
2015 | | * fallback to the corresp. proto if the built |
2016 | | * message > mtu and send_info->proto==PROTO_UDP. |
2017 | | * It will also update send_info->proto. |
2018 | | * - FL_FORCE_RPORT: add rport to via |
2019 | | * @param mode - flags for building the message, can be a combination of: |
2020 | | * * BUILD_NO_LOCAL_VIA - don't add a local via |
2021 | | * * BUILD_NO_VIA1_UPDATE - don't update first via (rport, |
2022 | | * received a.s.o) |
2023 | | * * BUILD_NO_PATH - don't add a Route: header with the |
2024 | | * msg->path_vec content. |
2025 | | * * BUILD_IN_SHM - build the result in shm memory |
2026 | | * |
2027 | | * @return pointer to the new request (pkg_malloc'ed or shm_malloc'ed, |
2028 | | * depending on the presence of the BUILD_IN_SHM flag, needs freeing when |
2029 | | * done) and sets returned_len or 0 on error. |
2030 | | */ |
2031 | | char *build_req_buf_from_sip_req(struct sip_msg *msg, |
2032 | | unsigned int *returned_len, struct dest_info *send_info, |
2033 | | unsigned int mode) |
2034 | 0 | { |
2035 | 0 | unsigned int len, new_len, received_len, rport_len, uri_len, via_len, |
2036 | 0 | body_delta; |
2037 | 0 | char *line_buf; |
2038 | 0 | char *received_buf; |
2039 | 0 | char *rport_buf; |
2040 | 0 | char *new_buf; |
2041 | 0 | char *buf; |
2042 | 0 | str path_buf; |
2043 | 0 | unsigned int offset, s_offset, size; |
2044 | 0 | struct lump *via_anchor; |
2045 | 0 | struct lump *via_lump; |
2046 | 0 | struct lump *via_rm; |
2047 | 0 | struct lump *via_insert_param; |
2048 | 0 | struct lump *path_anchor; |
2049 | 0 | struct lump *path_lump; |
2050 | 0 | str branch; |
2051 | 0 | unsigned int flags; |
2052 | 0 | unsigned int udp_mtu; |
2053 | 0 | struct dest_info di; |
2054 | 0 | int ret; |
2055 | |
|
2056 | 0 | via_insert_param = 0; |
2057 | 0 | uri_len = 0; |
2058 | 0 | buf = msg->buf; |
2059 | 0 | len = msg->len; |
2060 | 0 | received_len = 0; |
2061 | 0 | rport_len = 0; |
2062 | 0 | new_buf = 0; |
2063 | 0 | received_buf = 0; |
2064 | 0 | rport_buf = 0; |
2065 | 0 | via_anchor = 0; |
2066 | 0 | line_buf = 0; |
2067 | 0 | via_len = 0; |
2068 | 0 | path_buf.s = 0; |
2069 | 0 | path_buf.len = 0; |
2070 | |
|
2071 | 0 | flags = msg->msg_flags | global_req_flags; |
2072 | 0 | if((ret = check_boundaries(msg, send_info)) < 0) { |
2073 | 0 | LM_INFO("check boundaries negative (%d)\n", ret); |
2074 | 0 | } |
2075 | | |
2076 | | /* Calculate message body difference and adjust Content-Length */ |
2077 | 0 | body_delta = lumps_len(msg, msg->body_lumps, send_info); |
2078 | 0 | if(adjust_clen(msg, body_delta, send_info->proto) < 0) { |
2079 | 0 | LM_ERR("Error while adjusting Content-Length\n"); |
2080 | 0 | goto error00; |
2081 | 0 | } |
2082 | | |
2083 | 0 | if(unlikely(mode & BUILD_NO_LOCAL_VIA)) |
2084 | 0 | goto after_local_via; |
2085 | | |
2086 | | /* create the via header */ |
2087 | 0 | branch.s = msg->add_to_branch_s; |
2088 | 0 | branch.len = msg->add_to_branch_len; |
2089 | |
|
2090 | 0 | via_anchor = anchor_lump(msg, msg->via1->hdr.s - buf, 0, HDR_VIA_T); |
2091 | 0 | if(unlikely(via_anchor == 0)) |
2092 | 0 | goto error00; |
2093 | 0 | line_buf = create_via_hf(&via_len, msg, send_info, &branch); |
2094 | 0 | if(unlikely(!line_buf)) { |
2095 | 0 | LM_ERR("could not create Via header\n"); |
2096 | 0 | goto error00; |
2097 | 0 | } |
2098 | 0 | if(unlikely(mode & BUILD_NEW_LOCAL_VIA)) { |
2099 | | /* delete exiting top Via header */ |
2100 | 0 | via_rm = del_lump( |
2101 | 0 | msg, msg->h_via1->name.s - msg->buf, msg->h_via1->len, 0); |
2102 | 0 | if(via_rm == 0) { |
2103 | 0 | LM_ERR("failed to remove exiting Via header\n"); |
2104 | 0 | goto error00; |
2105 | 0 | } |
2106 | | /* do not update old Via header anymore */ |
2107 | 0 | mode |= BUILD_NO_VIA1_UPDATE; |
2108 | 0 | } |
2109 | 0 | after_local_via: |
2110 | 0 | if(unlikely(mode & BUILD_NO_VIA1_UPDATE)) |
2111 | 0 | goto after_update_via1; |
2112 | | /* check if received needs to be added */ |
2113 | 0 | if(received_test(msg)) { |
2114 | 0 | if((received_buf = received_builder(msg, &received_len)) == 0) { |
2115 | 0 | LM_ERR("received_builder failed\n"); |
2116 | 0 | goto error00; /* free also line_buf */ |
2117 | 0 | } |
2118 | 0 | } |
2119 | | |
2120 | | /* check if rport needs to be updated: |
2121 | | * - if FL_FORCE_RPORT is set add it (and del. any previous version) |
2122 | | * - if via already contains an rport add it and overwrite the previous |
2123 | | * rport value if present (if you don't want to overwrite the previous |
2124 | | * version remove the comments) */ |
2125 | 0 | if((flags & FL_FORCE_RPORT) |
2126 | 0 | || (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)) { |
2127 | 0 | if((rport_buf = rport_builder(msg, &rport_len)) == 0) { |
2128 | 0 | LM_ERR("rport_builder failed\n"); |
2129 | 0 | goto error00; /* free everything */ |
2130 | 0 | } |
2131 | 0 | } |
2132 | | |
2133 | | /* find out where the offset of the first parameter that should be added |
2134 | | * (after host:port), needed by add receive & maybe rport */ |
2135 | 0 | if(msg->via1->params.s) { |
2136 | 0 | size = msg->via1->params.s - msg->via1->hdr.s - 1; /*compensate |
2137 | | for ';' */ |
2138 | 0 | } else { |
2139 | 0 | size = msg->via1->host.s - msg->via1->hdr.s + msg->via1->host.len; |
2140 | 0 | if(msg->via1->port != 0) { |
2141 | | /*size+=strlen(msg->via1->hdr.s+size+1)+1;*/ |
2142 | 0 | size += msg->via1->port_str.len + 1; /* +1 for ':'*/ |
2143 | 0 | } |
2144 | | #if 0 |
2145 | | /* no longer necessary, now hots.s contains [] */ |
2146 | | if(send_sock->address.af==AF_INET6) size+=1; /* +1 for ']'*/ |
2147 | | #endif |
2148 | 0 | } |
2149 | | /* if received needs to be added, add anchor after host and add it, or |
2150 | | * overwrite the previous one if already present */ |
2151 | 0 | if(received_buf) { |
2152 | 0 | if(msg->via1->received) { /* received already present => overwrite it*/ |
2153 | 0 | via_insert_param = |
2154 | 0 | del_lump(msg, msg->via1->received->start - buf - 1, /*;*/ |
2155 | 0 | msg->via1->received->size + 1, /*;*/ HDR_VIA_T); |
2156 | 0 | } else if(via_insert_param == 0) { /* receive not present, ok */ |
2157 | 0 | via_insert_param = anchor_lump( |
2158 | 0 | msg, msg->via1->hdr.s - buf + size, 0, HDR_VIA_T); |
2159 | 0 | } |
2160 | 0 | if(via_insert_param == 0) |
2161 | 0 | goto error00; /* free received_buf */ |
2162 | 0 | if(insert_new_lump_after( |
2163 | 0 | via_insert_param, received_buf, received_len, HDR_VIA_T) |
2164 | 0 | == 0) { |
2165 | 0 | goto error00; /* free received_buf */ |
2166 | 0 | } |
2167 | 0 | received_buf = NULL; |
2168 | 0 | } |
2169 | | /* if rport needs to be updated, delete it if present and add its value */ |
2170 | 0 | if(rport_buf) { |
2171 | 0 | if(msg->via1->rport) { /* rport already present */ |
2172 | 0 | via_insert_param = |
2173 | 0 | del_lump(msg, msg->via1->rport->start - buf - 1, /*';'*/ |
2174 | 0 | msg->via1->rport->size + 1 /* ; */, HDR_VIA_T); |
2175 | 0 | } else if(via_insert_param == 0) { /*force rport, no rport present */ |
2176 | | /* no rport, add it */ |
2177 | 0 | via_insert_param = anchor_lump( |
2178 | 0 | msg, msg->via1->hdr.s - buf + size, 0, HDR_VIA_T); |
2179 | 0 | } |
2180 | 0 | if(via_insert_param == 0) |
2181 | 0 | goto error00; /* free rport_buf */ |
2182 | 0 | if(insert_new_lump_after( |
2183 | 0 | via_insert_param, rport_buf, rport_len, HDR_VIA_T) |
2184 | 0 | == 0) { |
2185 | 0 | goto error00; /* free rport_buf */ |
2186 | 0 | } |
2187 | 0 | rport_buf = NULL; |
2188 | 0 | } |
2189 | | |
2190 | 0 | after_update_via1: |
2191 | | /* add route with path content */ |
2192 | 0 | if(unlikely(!(mode & BUILD_NO_PATH) && msg->path_vec.s |
2193 | 0 | && msg->path_vec.len)) { |
2194 | 0 | path_buf.len = ROUTE_PREFIX_LEN + msg->path_vec.len + CRLF_LEN; |
2195 | 0 | path_buf.s = pkg_malloc(path_buf.len + 1); |
2196 | 0 | if(unlikely(path_buf.s == 0)) { |
2197 | 0 | PKG_MEM_ERROR; |
2198 | 0 | ser_error = E_OUT_OF_MEM; |
2199 | 0 | goto error00; |
2200 | 0 | } |
2201 | 0 | memcpy(path_buf.s, ROUTE_PREFIX, ROUTE_PREFIX_LEN); |
2202 | 0 | memcpy(path_buf.s + ROUTE_PREFIX_LEN, msg->path_vec.s, |
2203 | 0 | msg->path_vec.len); |
2204 | 0 | memcpy(path_buf.s + ROUTE_PREFIX_LEN + msg->path_vec.len, CRLF, |
2205 | 0 | CRLF_LEN); |
2206 | 0 | path_buf.s[path_buf.len] = 0; |
2207 | | /* insert Route header either before the other routes |
2208 | | (if present & parsed), after the local via or after in front of |
2209 | | the first via if we don't add a local via*/ |
2210 | 0 | if(msg->route) { |
2211 | 0 | path_anchor = |
2212 | 0 | anchor_lump(msg, msg->route->name.s - buf, 0, HDR_ROUTE_T); |
2213 | 0 | } else if(likely(via_anchor)) { |
2214 | 0 | path_anchor = via_anchor; |
2215 | 0 | } else if(likely(msg->via1)) { |
2216 | 0 | path_anchor = |
2217 | 0 | anchor_lump(msg, msg->via1->hdr.s - buf, 0, HDR_ROUTE_T); |
2218 | 0 | } else { |
2219 | | /* if no via1 (theoretically possible for non-sip messages, |
2220 | | e.g. http xmlrpc) */ |
2221 | 0 | path_anchor = anchor_lump( |
2222 | 0 | msg, msg->headers->name.s - buf, 0, HDR_ROUTE_T); |
2223 | 0 | } |
2224 | 0 | if(unlikely(path_anchor == 0)) |
2225 | 0 | goto error00; |
2226 | 0 | if(unlikely((path_lump = insert_new_lump_after(path_anchor, path_buf.s, |
2227 | 0 | path_buf.len, HDR_ROUTE_T)) |
2228 | 0 | == 0)) { |
2229 | 0 | goto error00; |
2230 | 0 | } |
2231 | 0 | path_buf.s = NULL; |
2232 | 0 | } |
2233 | | /* compute new msg len and fix overlapping zones*/ |
2234 | 0 | new_len = |
2235 | 0 | len + body_delta + lumps_len(msg, msg->add_rm, send_info) + via_len; |
2236 | | #ifdef XL_DEBUG |
2237 | | LM_ERR("new_len(%d)=len(%d)+lumps_len\n", new_len, len); |
2238 | | #endif |
2239 | 0 | udp_mtu = cfg_get(core, core_cfg, udp_mtu); |
2240 | 0 | di.proto = PROTO_NONE; |
2241 | 0 | if(unlikely((send_info->proto == PROTO_UDP) && udp_mtu |
2242 | 0 | && (flags & FL_MTU_FB_MASK) && (new_len > udp_mtu) |
2243 | 0 | && (!(mode & BUILD_NO_LOCAL_VIA)))) { |
2244 | |
|
2245 | 0 | di = *send_info; /* copy whole struct - will be used in the Via builder */ |
2246 | 0 | di.proto = PROTO_NONE; /* except the proto */ |
2247 | 0 | #ifdef USE_TCP |
2248 | 0 | if(!tcp_disable && (flags & FL_MTU_TCP_FB) |
2249 | 0 | && (di.send_sock = get_send_socket( |
2250 | 0 | msg, &send_info->to, PROTO_TCP))) { |
2251 | 0 | di.proto = PROTO_TCP; |
2252 | 0 | } |
2253 | 0 | #ifdef USE_TLS |
2254 | 0 | else if(!tls_disable && (flags & FL_MTU_TLS_FB) |
2255 | 0 | && (di.send_sock = get_send_socket( |
2256 | 0 | msg, &send_info->to, PROTO_TLS))) { |
2257 | 0 | di.proto = PROTO_TLS; |
2258 | 0 | } |
2259 | 0 | #endif /* USE_TLS */ |
2260 | 0 | #endif /* USE_TCP */ |
2261 | 0 | #ifdef USE_SCTP |
2262 | 0 | #ifdef USE_TCP |
2263 | 0 | else |
2264 | 0 | #endif /* USE_TCP */ |
2265 | 0 | if(!sctp_disable && (flags & FL_MTU_SCTP_FB) |
2266 | 0 | && (di.send_sock = get_send_socket( |
2267 | 0 | msg, &send_info->to, PROTO_SCTP))) { |
2268 | 0 | di.proto = PROTO_SCTP; |
2269 | 0 | } |
2270 | 0 | #endif /* USE_SCTP */ |
2271 | |
|
2272 | 0 | if(di.proto != PROTO_NONE) { |
2273 | 0 | new_len -= via_len; |
2274 | 0 | if(likely(line_buf)) |
2275 | 0 | pkg_free(line_buf); |
2276 | 0 | line_buf = create_via_hf(&via_len, msg, &di, &branch); |
2277 | 0 | if(!line_buf) { |
2278 | 0 | LM_ERR("memory allocation failure!\n"); |
2279 | 0 | goto error00; |
2280 | 0 | } |
2281 | 0 | new_len += via_len; |
2282 | 0 | } |
2283 | 0 | } |
2284 | | /* add via header to the list */ |
2285 | | /* try to add it before msg. 1st via */ |
2286 | | /* add first via, as an anchor for second via*/ |
2287 | 0 | if(likely(line_buf)) { |
2288 | 0 | if((via_lump = insert_new_lump_before( |
2289 | 0 | via_anchor, line_buf, via_len, HDR_VIA_T)) |
2290 | 0 | == 0) { |
2291 | 0 | goto error00; |
2292 | 0 | } |
2293 | 0 | line_buf = 0; |
2294 | 0 | } |
2295 | 0 | if(msg->new_uri.s) { |
2296 | 0 | uri_len = msg->new_uri.len; |
2297 | 0 | new_len = new_len - msg->first_line.u.request.uri.len + uri_len; |
2298 | 0 | } |
2299 | 0 | if(unlikely(mode & BUILD_IN_SHM)) |
2300 | 0 | new_buf = (char *)shm_malloc(new_len + 1); |
2301 | 0 | else |
2302 | 0 | new_buf = (char *)pkg_malloc(new_len + 1); |
2303 | 0 | if(new_buf == 0) { |
2304 | 0 | ser_error = E_OUT_OF_MEM; |
2305 | 0 | if(unlikely(mode & BUILD_IN_SHM)) { |
2306 | 0 | SHM_MEM_ERROR; |
2307 | 0 | } else { |
2308 | 0 | PKG_MEM_ERROR; |
2309 | 0 | } |
2310 | 0 | goto error00; |
2311 | 0 | } |
2312 | | |
2313 | 0 | offset = s_offset = 0; |
2314 | 0 | if(msg->new_uri.s) { |
2315 | | /* copy message up to uri */ |
2316 | 0 | size = msg->first_line.u.request.uri.s - buf; |
2317 | 0 | memcpy(new_buf, buf, size); |
2318 | 0 | offset += size; |
2319 | 0 | s_offset += size; |
2320 | | /* add our uri */ |
2321 | 0 | memcpy(new_buf + offset, msg->new_uri.s, uri_len); |
2322 | 0 | offset += uri_len; |
2323 | 0 | s_offset += msg->first_line.u.request.uri.len; /* skip original uri */ |
2324 | 0 | } |
2325 | 0 | new_buf[new_len] = 0; |
2326 | | /* copy msg adding/removing lumps */ |
2327 | 0 | process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, |
2328 | 0 | FLAG_MSG_ALL); |
2329 | 0 | process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info, |
2330 | 0 | FLAG_MSG_ALL); |
2331 | | /* copy the rest of the message */ |
2332 | 0 | memcpy(new_buf + offset, buf + s_offset, len - s_offset); |
2333 | 0 | new_buf[new_len] = 0; |
2334 | | |
2335 | | /* update the send_info if udp_mtu affected */ |
2336 | 0 | if(di.proto != PROTO_NONE) { |
2337 | 0 | send_info->proto = di.proto; |
2338 | 0 | send_info->send_sock = di.send_sock; |
2339 | 0 | } |
2340 | |
|
2341 | | #ifdef DBG_MSG_QA |
2342 | | if(new_buf[new_len - 1] == 0) { |
2343 | | LM_ERR("0 in the end\n"); |
2344 | | abort(); |
2345 | | } |
2346 | | #endif |
2347 | |
|
2348 | 0 | *returned_len = new_len; |
2349 | 0 | return new_buf; |
2350 | | |
2351 | 0 | error00: |
2352 | 0 | if(received_buf) |
2353 | 0 | pkg_free(received_buf); |
2354 | 0 | if(rport_buf) |
2355 | 0 | pkg_free(rport_buf); |
2356 | 0 | if(path_buf.s) |
2357 | 0 | pkg_free(path_buf.s); |
2358 | 0 | if(line_buf) |
2359 | 0 | pkg_free(line_buf); |
2360 | |
|
2361 | 0 | *returned_len = 0; |
2362 | 0 | return 0; |
2363 | 0 | } |
2364 | | |
2365 | | char *generate_res_buf_from_sip_res( |
2366 | | struct sip_msg *msg, unsigned int *returned_len, unsigned int mode) |
2367 | 0 | { |
2368 | 0 | unsigned int new_len, via_len, body_delta; |
2369 | 0 | char *new_buf; |
2370 | 0 | unsigned offset, s_offset, via_offset; |
2371 | 0 | char *buf; |
2372 | 0 | unsigned int len; |
2373 | 0 | str xparams; |
2374 | 0 | sr_lump_t *anchor; |
2375 | |
|
2376 | 0 | buf = msg->buf; |
2377 | 0 | len = msg->len; |
2378 | 0 | new_buf = 0; |
2379 | |
|
2380 | 0 | if(unlikely(mode & BUILD_NO_VIA1_UPDATE)) { |
2381 | 0 | via_len = 0; |
2382 | 0 | via_offset = 0; |
2383 | 0 | } else { |
2384 | | /* we must remove the first via */ |
2385 | 0 | if(msg->via1->next) { |
2386 | 0 | via_len = msg->via1->bsize; |
2387 | 0 | via_offset = msg->h_via1->body.s - buf; |
2388 | 0 | } else { |
2389 | 0 | via_len = msg->h_via1->len; |
2390 | 0 | via_offset = msg->h_via1->name.s - buf; |
2391 | 0 | } |
2392 | 0 | } |
2393 | | |
2394 | | /* test and add xavp via reply params */ |
2395 | 0 | if(msg && msg->via2 && (msg->msg_flags & FL_ADD_XAVP_VIA_REPLY_PARAMS) |
2396 | 0 | && _ksr_xavp_via_reply_params.len > 0) { |
2397 | 0 | xparams.s = pv_get_buffer(); |
2398 | 0 | xparams.len = xavp_serialize_fields_style(&_ksr_xavp_via_reply_params, |
2399 | 0 | 1, xparams.s, pv_get_buffer_size()); |
2400 | 0 | if(xparams.len > 0) { |
2401 | 0 | LM_DBG("adding via reply xavp params\n"); |
2402 | 0 | anchor = anchor_lump(msg, |
2403 | 0 | msg->via2->params.s + msg->via2->params.len - msg->buf, 0, |
2404 | 0 | 0); |
2405 | 0 | if(anchor != NULL) { |
2406 | 0 | if(insert_new_lump_after(anchor, xparams.s, xparams.len, 0) |
2407 | 0 | == 0) { |
2408 | 0 | LM_ERR("unable to add via reply xavp params\n"); |
2409 | 0 | } |
2410 | 0 | } |
2411 | 0 | } |
2412 | 0 | } |
2413 | | |
2414 | | /* Calculate message body difference and adjust |
2415 | | * Content-Length |
2416 | | */ |
2417 | 0 | body_delta = lumps_len(msg, msg->body_lumps, 0); |
2418 | 0 | if(adjust_clen(msg, body_delta, (msg->via2 ? msg->via2->proto : PROTO_UDP)) |
2419 | 0 | < 0) { |
2420 | 0 | LM_ERR("error while adjusting Content-Length\n"); |
2421 | 0 | goto error; |
2422 | 0 | } |
2423 | | |
2424 | 0 | if(likely(!(mode & BUILD_NO_VIA1_UPDATE))) { |
2425 | | /* remove the first via*/ |
2426 | 0 | if(del_lump(msg, via_offset, via_len, HDR_VIA_T) == 0) { |
2427 | 0 | LM_ERR("error trying to remove first via\n"); |
2428 | 0 | goto error; |
2429 | 0 | } |
2430 | 0 | } |
2431 | | |
2432 | 0 | new_len = |
2433 | 0 | len + body_delta + lumps_len(msg, msg->add_rm, 0); /*FIXME: we don't |
2434 | | know the send sock */ |
2435 | |
|
2436 | 0 | LM_DBG("old size: %d, new size: %d\n", len, new_len); |
2437 | 0 | new_buf = (char *)pkg_malloc(new_len + 1); /* +1 is for debugging |
2438 | | (\0 to print it )*/ |
2439 | 0 | if(new_buf == 0) { |
2440 | 0 | PKG_MEM_ERROR; |
2441 | 0 | goto error; |
2442 | 0 | } |
2443 | 0 | new_buf[new_len] = 0; /* debug: print the message */ |
2444 | 0 | offset = s_offset = 0; |
2445 | | /*FIXME: no send sock*/ |
2446 | 0 | process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, 0, |
2447 | 0 | FLAG_MSG_ALL); /*FIXME:*/ |
2448 | 0 | process_lumps( |
2449 | 0 | msg, msg->body_lumps, new_buf, &offset, &s_offset, 0, FLAG_MSG_ALL); |
2450 | | /* copy the rest of the message */ |
2451 | 0 | memcpy(new_buf + offset, buf + s_offset, len - s_offset); |
2452 | | /* send it! */ |
2453 | 0 | LM_DBG("copied size: orig:%d, new: %d, rest: %d msg=\n%s\n", s_offset, |
2454 | 0 | offset, len - s_offset, new_buf); |
2455 | |
|
2456 | 0 | *returned_len = new_len; |
2457 | 0 | return new_buf; |
2458 | 0 | error: |
2459 | 0 | *returned_len = 0; |
2460 | 0 | return 0; |
2461 | 0 | } |
2462 | | |
2463 | | char *build_res_buf_from_sip_res( |
2464 | | struct sip_msg *msg, unsigned int *returned_len) |
2465 | 0 | { |
2466 | 0 | return generate_res_buf_from_sip_res(msg, returned_len, 0); |
2467 | 0 | } |
2468 | | |
2469 | | char *build_res_buf_from_sip_req(unsigned int code, str *text, str *new_tag, |
2470 | | struct sip_msg *msg, unsigned int *returned_len, struct bookmark *bmark) |
2471 | 0 | { |
2472 | 0 | char *buf, *p; |
2473 | 0 | unsigned int len, foo; |
2474 | 0 | struct hdr_field *hdr; |
2475 | 0 | struct lump_rpl *lump; |
2476 | 0 | struct lump_rpl *body; |
2477 | 0 | int i; |
2478 | 0 | char *received_buf; |
2479 | 0 | unsigned int received_len; |
2480 | 0 | char *rport_buf; |
2481 | 0 | unsigned int rport_len; |
2482 | 0 | char *warning_buf; |
2483 | 0 | unsigned int warning_len; |
2484 | 0 | char *content_len_buf; |
2485 | 0 | unsigned int content_len_len; |
2486 | 0 | char *after_body; |
2487 | 0 | str to_tag; |
2488 | 0 | char *totags; |
2489 | 0 | int httpreq; |
2490 | 0 | char *pvia; |
2491 | 0 | str xparams = STR_NULL; |
2492 | |
|
2493 | 0 | body = 0; |
2494 | 0 | buf = 0; |
2495 | 0 | received_buf = rport_buf = warning_buf = content_len_buf = 0; |
2496 | 0 | received_len = rport_len = warning_len = content_len_len = 0; |
2497 | |
|
2498 | 0 | to_tag.s = 0; /* fixes gcc 4.0 warning */ |
2499 | 0 | to_tag.len = 0; |
2500 | | |
2501 | | /* force parsing all headers -- we want to return all |
2502 | | Via's in the reply and they may be scattered down to the |
2503 | | end of header (non-block Vias are a really poor property |
2504 | | of SIP :( ) */ |
2505 | 0 | if(parse_headers(msg, HDR_EOH_F, 0) == -1) { |
2506 | 0 | LM_ERR("alas, parse_headers failed\n"); |
2507 | 0 | goto error00; |
2508 | 0 | } |
2509 | | |
2510 | | /*computes the length of the new response buffer*/ |
2511 | 0 | len = 0; |
2512 | |
|
2513 | 0 | httpreq = IS_HTTP(msg); |
2514 | | |
2515 | | /* check if received needs to be added */ |
2516 | 0 | if(received_test(msg)) { |
2517 | 0 | if((received_buf = received_builder(msg, &received_len)) == 0) { |
2518 | 0 | LM_ERR("alas, received_builder failed\n"); |
2519 | 0 | goto error00; |
2520 | 0 | } |
2521 | 0 | } |
2522 | | /* check if rport needs to be updated */ |
2523 | 0 | if(((msg->msg_flags | global_req_flags) & FL_FORCE_RPORT) |
2524 | 0 | || (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)) { |
2525 | 0 | if((rport_buf = rport_builder(msg, &rport_len)) == 0) { |
2526 | 0 | LM_ERR("rport_builder failed\n"); |
2527 | 0 | goto error01; /* free everything */ |
2528 | 0 | } |
2529 | 0 | if(msg->via1->rport) |
2530 | 0 | len -= msg->via1->rport->size + 1; /* include ';' */ |
2531 | 0 | } |
2532 | | |
2533 | | /* test and add xavp via reply params */ |
2534 | 0 | if(msg && (msg->msg_flags & FL_ADD_XAVP_VIA_REPLY_PARAMS) |
2535 | 0 | && _ksr_xavp_via_reply_params.len > 0) { |
2536 | 0 | xparams.s = pv_get_buffer(); |
2537 | 0 | xparams.len = xavp_serialize_fields_style(&_ksr_xavp_via_reply_params, |
2538 | 0 | 1, xparams.s, pv_get_buffer_size()); |
2539 | 0 | if(xparams.len > 0) { |
2540 | 0 | len += xparams.len; /* starting ';' included */ |
2541 | 0 | } |
2542 | 0 | } |
2543 | | |
2544 | | /* first line */ |
2545 | 0 | len += msg->first_line.u.request.version.len |
2546 | 0 | + 1 /*space*/ + 3 /*code*/ + 1 /*space*/ + text->len |
2547 | 0 | + CRLF_LEN /*new line*/; |
2548 | | /*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/ |
2549 | 0 | for(hdr = msg->headers; hdr; hdr = hdr->next) { |
2550 | 0 | switch(hdr->type) { |
2551 | 0 | case HDR_TO_T: |
2552 | 0 | if(new_tag && new_tag->len) { |
2553 | 0 | to_tag = get_to(msg)->tag_value; |
2554 | 0 | if(to_tag.len && to_tag.s) |
2555 | 0 | len += new_tag->len - to_tag.len; |
2556 | 0 | else |
2557 | 0 | len += new_tag->len + TOTAG_TOKEN_LEN /*";tag="*/; |
2558 | 0 | } |
2559 | 0 | len += hdr->len; |
2560 | 0 | break; |
2561 | 0 | case HDR_VIA_T: |
2562 | | /* we always add CRLF to via*/ |
2563 | 0 | len += (hdr->body.s + hdr->body.len) - hdr->name.s + CRLF_LEN; |
2564 | 0 | if(hdr == msg->h_via1) |
2565 | 0 | len += received_len + rport_len; |
2566 | 0 | break; |
2567 | 0 | case HDR_RECORDROUTE_T: |
2568 | | /* RR only for 1xx and 2xx replies */ |
2569 | 0 | if(code < 180 || code >= 300) |
2570 | 0 | break; |
2571 | 0 | case HDR_FROM_T: |
2572 | 0 | case HDR_CALLID_T: |
2573 | 0 | case HDR_CSEQ_T: |
2574 | | /* we keep the original termination for these headers*/ |
2575 | 0 | len += hdr->len; |
2576 | 0 | break; |
2577 | 0 | default: |
2578 | | /* do nothing, we are interested only in the above headers */ |
2579 | 0 | ; |
2580 | 0 | } |
2581 | 0 | } |
2582 | | /* lumps length */ |
2583 | 0 | for(lump = msg->reply_lump; lump; lump = lump->next) { |
2584 | 0 | len += lump->text.len; |
2585 | 0 | if(lump->flags & LUMP_RPL_BODY) |
2586 | 0 | body = lump; |
2587 | 0 | } |
2588 | | /* server header */ |
2589 | 0 | if(server_signature && server_hdr.len) |
2590 | 0 | len += server_hdr.len + CRLF_LEN; |
2591 | | /* warning hdr */ |
2592 | 0 | if(sip_warning) { |
2593 | 0 | warning_buf = warning_builder(msg, &warning_len); |
2594 | 0 | if(warning_buf) |
2595 | 0 | len += warning_len + CRLF_LEN; |
2596 | 0 | else |
2597 | 0 | LM_WARN("warning skipped -- too big\n"); |
2598 | 0 | } |
2599 | | /* content length hdr */ |
2600 | 0 | if(body) { |
2601 | 0 | content_len_buf = int2str(body->text.len, (int *)&content_len_len); |
2602 | 0 | len += CONTENT_LENGTH_LEN + content_len_len + CRLF_LEN; |
2603 | 0 | } else { |
2604 | 0 | len += CONTENT_LENGTH_LEN + 1 /*0*/ + CRLF_LEN; |
2605 | 0 | } |
2606 | | /* end of message */ |
2607 | 0 | len += CRLF_LEN; /*new line*/ |
2608 | | |
2609 | | /*allocating mem*/ |
2610 | 0 | buf = (char *)pkg_malloc(len + 1); |
2611 | 0 | if(!buf) { |
2612 | 0 | PKG_MEM_ERROR; |
2613 | 0 | goto error01; |
2614 | 0 | } |
2615 | | |
2616 | | /* filling the buffer*/ |
2617 | 0 | p = buf; |
2618 | | /* first line */ |
2619 | 0 | memcpy(p, msg->first_line.u.request.version.s, |
2620 | 0 | msg->first_line.u.request.version.len); |
2621 | 0 | p += msg->first_line.u.request.version.len; |
2622 | 0 | *(p++) = ' '; |
2623 | | /*code*/ |
2624 | 0 | for(i = 2, foo = code; i >= 0; i--, foo = foo / 10) |
2625 | 0 | *(p + i) = '0' + foo - (foo / 10) * 10; |
2626 | 0 | p += 3; |
2627 | 0 | *(p++) = ' '; |
2628 | 0 | memcpy(p, text->s, text->len); |
2629 | 0 | p += text->len; |
2630 | 0 | memcpy(p, CRLF, CRLF_LEN); |
2631 | 0 | p += CRLF_LEN; |
2632 | | /* headers*/ |
2633 | 0 | for(hdr = msg->headers; hdr; hdr = hdr->next) { |
2634 | 0 | switch(hdr->type) { |
2635 | 0 | case HDR_VIA_T: |
2636 | | /* if is HTTP, backup start of Via header in response */ |
2637 | 0 | if(unlikely(httpreq)) |
2638 | 0 | pvia = p; |
2639 | 0 | if(hdr == msg->h_via1) { |
2640 | 0 | if(rport_buf) { |
2641 | 0 | if(msg->via1->rport) { /* delete the old one */ |
2642 | | /* copy until rport */ |
2643 | 0 | append_str_trans(p, hdr->name.s, |
2644 | 0 | msg->via1->rport->start - hdr->name.s - 1, |
2645 | 0 | msg); |
2646 | | /* copy new rport */ |
2647 | 0 | append_str(p, rport_buf, rport_len); |
2648 | | /* copy the rest of the via */ |
2649 | 0 | append_str_trans(p, |
2650 | 0 | msg->via1->rport->start |
2651 | 0 | + msg->via1->rport->size, |
2652 | 0 | hdr->body.s + hdr->body.len |
2653 | 0 | - msg->via1->rport->start |
2654 | 0 | - msg->via1->rport->size, |
2655 | 0 | msg); |
2656 | 0 | } else { /* just append the new one */ |
2657 | | /* normal whole via copy */ |
2658 | 0 | append_str_trans(p, hdr->name.s, |
2659 | 0 | (hdr->body.s + hdr->body.len) - hdr->name.s, |
2660 | 0 | msg); |
2661 | 0 | append_str(p, rport_buf, rport_len); |
2662 | 0 | } |
2663 | 0 | } else { |
2664 | | /* normal whole via copy */ |
2665 | 0 | append_str_trans(p, hdr->name.s, |
2666 | 0 | (hdr->body.s + hdr->body.len) - hdr->name.s, |
2667 | 0 | msg); |
2668 | 0 | } |
2669 | 0 | if(received_buf) |
2670 | 0 | append_str(p, received_buf, received_len); |
2671 | 0 | } else { |
2672 | | /* normal whole via copy */ |
2673 | 0 | append_str_trans(p, hdr->name.s, |
2674 | 0 | (hdr->body.s + hdr->body.len) - hdr->name.s, msg); |
2675 | 0 | } |
2676 | 0 | if(xparams.len > 0) { |
2677 | 0 | append_str(p, xparams.s, xparams.len); |
2678 | 0 | } |
2679 | 0 | append_str(p, CRLF, CRLF_LEN); |
2680 | | /* if is HTTP, replace Via with Sia |
2681 | | * - HTTP Via format is different than SIP Via |
2682 | | */ |
2683 | 0 | if(unlikely(httpreq)) |
2684 | 0 | *pvia = 'S'; |
2685 | 0 | break; |
2686 | 0 | case HDR_RECORDROUTE_T: |
2687 | | /* RR only for 1xx and 2xx replies */ |
2688 | 0 | if(code < 180 || code >= 300) |
2689 | 0 | break; |
2690 | 0 | append_str(p, hdr->name.s, hdr->len); |
2691 | 0 | break; |
2692 | 0 | case HDR_TO_T: |
2693 | 0 | if(new_tag && new_tag->len) { |
2694 | 0 | if(to_tag.len && to_tag.s) { /* replacement */ |
2695 | | /* before to-tag */ |
2696 | 0 | append_str(p, hdr->name.s, to_tag.s - hdr->name.s); |
2697 | | /* to tag replacement */ |
2698 | 0 | bmark->to_tag_val.s = p; |
2699 | 0 | bmark->to_tag_val.len = new_tag->len; |
2700 | 0 | append_str(p, new_tag->s, new_tag->len); |
2701 | | /* the rest after to-tag */ |
2702 | 0 | append_str(p, to_tag.s + to_tag.len, |
2703 | 0 | hdr->name.s + hdr->len |
2704 | 0 | - (to_tag.s + to_tag.len)); |
2705 | 0 | } else { /* adding a new to-tag */ |
2706 | 0 | after_body = hdr->body.s + hdr->body.len; |
2707 | 0 | append_str(p, hdr->name.s, after_body - hdr->name.s); |
2708 | 0 | append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN); |
2709 | 0 | bmark->to_tag_val.s = p; |
2710 | 0 | bmark->to_tag_val.len = new_tag->len; |
2711 | 0 | append_str(p, new_tag->s, new_tag->len); |
2712 | 0 | append_str(p, after_body, |
2713 | 0 | hdr->name.s + hdr->len - after_body); |
2714 | 0 | } |
2715 | 0 | break; |
2716 | 0 | } /* no new to-tag -- proceed to 1:1 copying */ |
2717 | 0 | totags = ((struct to_body *)(hdr->parsed))->tag_value.s; |
2718 | 0 | if(totags) { |
2719 | 0 | bmark->to_tag_val.s = p + (totags - hdr->name.s); |
2720 | 0 | bmark->to_tag_val.len = |
2721 | 0 | ((struct to_body *)(hdr->parsed))->tag_value.len; |
2722 | 0 | } else { |
2723 | 0 | bmark->to_tag_val.len = 0; |
2724 | 0 | bmark->to_tag_val.s = |
2725 | 0 | p + (hdr->body.s + hdr->body.len - hdr->name.s); |
2726 | 0 | } |
2727 | | /* no break */ |
2728 | 0 | case HDR_FROM_T: |
2729 | 0 | case HDR_CALLID_T: |
2730 | 0 | case HDR_CSEQ_T: |
2731 | 0 | append_str(p, hdr->name.s, hdr->len); |
2732 | 0 | break; |
2733 | 0 | default: |
2734 | | /* do nothing, we are interested only in the above headers */ |
2735 | 0 | ; |
2736 | 0 | } /* end switch */ |
2737 | 0 | } /* end for */ |
2738 | | /* lumps */ |
2739 | 0 | for(lump = msg->reply_lump; lump; lump = lump->next) |
2740 | 0 | if(lump->flags & LUMP_RPL_HDR) { |
2741 | 0 | memcpy(p, lump->text.s, lump->text.len); |
2742 | 0 | p += lump->text.len; |
2743 | 0 | } |
2744 | | /* server header */ |
2745 | 0 | if(server_signature && server_hdr.len > 0) { |
2746 | 0 | memcpy(p, server_hdr.s, server_hdr.len); |
2747 | 0 | p += server_hdr.len; |
2748 | 0 | memcpy(p, CRLF, CRLF_LEN); |
2749 | 0 | p += CRLF_LEN; |
2750 | 0 | } |
2751 | | /* content_length hdr */ |
2752 | 0 | if(content_len_len) { |
2753 | 0 | append_str(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN); |
2754 | 0 | append_str(p, content_len_buf, content_len_len); |
2755 | 0 | append_str(p, CRLF, CRLF_LEN); |
2756 | 0 | } else { |
2757 | 0 | append_str( |
2758 | 0 | p, CONTENT_LENGTH "0" CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN); |
2759 | 0 | } |
2760 | | /* warning header */ |
2761 | 0 | if(warning_buf) { |
2762 | 0 | memcpy(p, warning_buf, warning_len); |
2763 | 0 | p += warning_len; |
2764 | 0 | memcpy(p, CRLF, CRLF_LEN); |
2765 | 0 | p += CRLF_LEN; |
2766 | 0 | } |
2767 | | /*end of message*/ |
2768 | 0 | memcpy(p, CRLF, CRLF_LEN); |
2769 | 0 | p += CRLF_LEN; |
2770 | | /* body */ |
2771 | 0 | if(body) { |
2772 | 0 | memcpy(p, body->text.s, body->text.len); |
2773 | 0 | p += body->text.len; |
2774 | 0 | } |
2775 | |
|
2776 | 0 | if(len != p - buf) |
2777 | 0 | LM_CRIT("diff len=%d p-buf=%d\n", len, (int)(p - buf)); |
2778 | |
|
2779 | 0 | *(p) = 0; |
2780 | 0 | *returned_len = len; |
2781 | | /* in req2reply, received_buf is not introduced to lumps and |
2782 | | needs to be deleted here |
2783 | | */ |
2784 | 0 | if(received_buf) |
2785 | 0 | pkg_free(received_buf); |
2786 | 0 | if(rport_buf) |
2787 | 0 | pkg_free(rport_buf); |
2788 | 0 | return buf; |
2789 | | |
2790 | 0 | error01: |
2791 | 0 | if(received_buf) |
2792 | 0 | pkg_free(received_buf); |
2793 | 0 | if(rport_buf) |
2794 | 0 | pkg_free(rport_buf); |
2795 | 0 | error00: |
2796 | 0 | *returned_len = 0; |
2797 | 0 | return 0; |
2798 | 0 | } |
2799 | | |
2800 | | |
2801 | | /* return number of chars printed or 0 if space exceeded; |
2802 | | assumes buffer size of at least MAX_BRANCH_PARAM_LEN |
2803 | | */ |
2804 | | int branch_builder(unsigned int hash_index, |
2805 | | /* only either parameter useful */ |
2806 | | unsigned int label, char *char_v, int branch, char *branch_str, |
2807 | | int *len) |
2808 | 0 | { |
2809 | |
|
2810 | 0 | char *begin; |
2811 | 0 | int size; |
2812 | | |
2813 | | /* hash id provided ... start with it */ |
2814 | 0 | size = MAX_BRANCH_PARAM_LEN; |
2815 | 0 | begin = branch_str; |
2816 | 0 | *len = 0; |
2817 | |
|
2818 | 0 | memcpy(begin, MCOOKIE, MCOOKIE_LEN); |
2819 | 0 | size -= MCOOKIE_LEN; |
2820 | 0 | begin += MCOOKIE_LEN; |
2821 | |
|
2822 | 0 | if(int2reverse_hex(&begin, &size, hash_index) == -1) |
2823 | 0 | return 0; |
2824 | | |
2825 | 0 | if(size) { |
2826 | 0 | *begin = BRANCH_SEPARATOR; |
2827 | 0 | begin++; |
2828 | 0 | size--; |
2829 | 0 | } else |
2830 | 0 | return 0; |
2831 | | |
2832 | | /* string with request's characteristic value ... use it ... */ |
2833 | 0 | if(char_v) { |
2834 | 0 | if(memcpy(begin, char_v, MD5_LEN)) { |
2835 | 0 | begin += MD5_LEN; |
2836 | 0 | size -= MD5_LEN; |
2837 | 0 | } else |
2838 | 0 | return 0; |
2839 | 0 | } else { /* ... use the "label" value otherwise */ |
2840 | 0 | if(int2reverse_hex(&begin, &size, label) == -1) |
2841 | 0 | return 0; |
2842 | 0 | } |
2843 | | |
2844 | 0 | if(size) { |
2845 | 0 | *begin = BRANCH_SEPARATOR; |
2846 | 0 | begin++; |
2847 | 0 | size--; |
2848 | 0 | } else |
2849 | 0 | return 0; |
2850 | | |
2851 | 0 | if(int2reverse_hex(&begin, &size, branch) == -1) |
2852 | 0 | return 0; |
2853 | | |
2854 | 0 | *len = MAX_BRANCH_PARAM_LEN - size; |
2855 | 0 | return size; |
2856 | 0 | } |
2857 | | |
2858 | | |
2859 | | /* uses only the send_info->send_socket, send_info->proto, send_info->id and |
2860 | | * send_info->comp (so that a send_info used for sending can be passed |
2861 | | * to this function w/o changes and the correct via will be built) */ |
2862 | | char *via_builder(unsigned int *len, sip_msg_t *msg, |
2863 | | struct dest_info *send_info /* where to send the reply */, str *branch, |
2864 | | str *extra_params, struct hostport *hp) |
2865 | 0 | { |
2866 | 0 | unsigned int via_len, extra_len; |
2867 | 0 | char *line_buf; |
2868 | 0 | int max_len; |
2869 | 0 | int via_prefix_len; |
2870 | 0 | str *address_str = NULL; /* address displayed in via */ |
2871 | 0 | str *port_str = NULL; /* port no displayed in via */ |
2872 | 0 | struct socket_info *send_sock; |
2873 | 0 | int comp_len, comp_name_len; |
2874 | | #ifdef USE_COMP |
2875 | | char *comp_name; |
2876 | | #endif /* USE_COMP */ |
2877 | 0 | int port; |
2878 | 0 | int proto; |
2879 | 0 | struct ip_addr ip; |
2880 | 0 | union sockaddr_union *from = NULL; |
2881 | 0 | union sockaddr_union local_addr; |
2882 | 0 | struct tcp_connection *con = NULL; |
2883 | 0 | sr_xavp_t *rxavp = NULL; |
2884 | 0 | str xname; |
2885 | |
|
2886 | 0 | send_sock = send_info->send_sock; |
2887 | | /* use pre-set address in via, the outbound socket alias or address one */ |
2888 | 0 | if(msg && (msg->msg_flags & FL_USE_XAVP_VIA_FIELDS) |
2889 | 0 | && _ksr_xavp_via_fields.len > 0) { |
2890 | 0 | xname.s = "address"; |
2891 | 0 | xname.len = 7; |
2892 | 0 | rxavp = xavp_get_child_with_sval(&_ksr_xavp_via_fields, &xname); |
2893 | 0 | if(rxavp != NULL) { |
2894 | 0 | address_str = &rxavp->val.v.s; |
2895 | 0 | } |
2896 | 0 | } |
2897 | 0 | if(address_str == NULL) { |
2898 | 0 | if(hp && hp->host->len) |
2899 | 0 | address_str = hp->host; |
2900 | 0 | else if(send_sock->useinfo.name.len > 0) |
2901 | 0 | address_str = &(send_sock->useinfo.name); |
2902 | 0 | else |
2903 | 0 | address_str = &(send_sock->address_str); |
2904 | 0 | } |
2905 | 0 | if(msg && (msg->msg_flags & FL_USE_XAVP_VIA_FIELDS) |
2906 | 0 | && _ksr_xavp_via_fields.len > 0) { |
2907 | 0 | xname.s = "port"; |
2908 | 0 | xname.len = 4; |
2909 | 0 | rxavp = xavp_get_child_with_sval(&_ksr_xavp_via_fields, &xname); |
2910 | 0 | if(rxavp != NULL) { |
2911 | 0 | port_str = &rxavp->val.v.s; |
2912 | 0 | } |
2913 | 0 | } |
2914 | 0 | if(port_str == NULL) { |
2915 | 0 | if(hp && hp->port->len) |
2916 | 0 | port_str = hp->port; |
2917 | 0 | else if(send_sock->useinfo.port_no > 0) |
2918 | 0 | port_str = &(send_sock->useinfo.port_no_str); |
2919 | 0 | else |
2920 | 0 | port_str = &(send_sock->port_no_str); |
2921 | 0 | } |
2922 | 0 | proto = PROTO_NONE; |
2923 | 0 | if(msg && (msg->msg_flags & FL_USE_XAVP_VIA_FIELDS) |
2924 | 0 | && _ksr_xavp_via_fields.len > 0) { |
2925 | 0 | xname.s = "proto"; |
2926 | 0 | xname.len = 5; |
2927 | 0 | rxavp = xavp_get_child_with_sval(&_ksr_xavp_via_fields, &xname); |
2928 | 0 | if(rxavp != NULL) { |
2929 | 0 | proto = get_valid_proto_id(&rxavp->val.v.s); |
2930 | 0 | } |
2931 | 0 | } |
2932 | 0 | if(proto == PROTO_NONE) { |
2933 | 0 | if(send_sock->useinfo.proto != PROTO_NONE) { |
2934 | 0 | proto = send_sock->useinfo.proto; |
2935 | 0 | } else { |
2936 | 0 | proto = send_info->proto; |
2937 | 0 | } |
2938 | 0 | } |
2939 | 0 | comp_len = comp_name_len = 0; |
2940 | | #ifdef USE_COMP |
2941 | | comp_name = 0; |
2942 | | switch(send_info->comp) { |
2943 | | case COMP_NONE: |
2944 | | break; |
2945 | | case COMP_SIGCOMP: |
2946 | | comp_len = COMP_PARAM_LEN; |
2947 | | comp_name_len = SIGCOMP_NAME_LEN; |
2948 | | comp_name = SIGCOMP_NAME; |
2949 | | break; |
2950 | | case COMP_SERGZ: |
2951 | | comp_len = COMP_PARAM_LEN; |
2952 | | comp_name_len = SERGZ_NAME_LEN; |
2953 | | comp_name = SERGZ_NAME; |
2954 | | break; |
2955 | | default: |
2956 | | LM_CRIT("unknown comp %d\n", send_info->comp); |
2957 | | /* continue, we'll just ignore comp */ |
2958 | | } |
2959 | | #endif /* USE_COMP */ |
2960 | |
|
2961 | 0 | via_prefix_len = MY_VIA_LEN + (proto == PROTO_SCTP); |
2962 | 0 | max_len = via_prefix_len + address_str->len /* space in MY_VIA */ |
2963 | 0 | + 2 /* just in case it is a v6 address ... [ ] */ |
2964 | 0 | + 1 /*':'*/ + port_str->len |
2965 | 0 | + (branch ? (MY_BRANCH_LEN + branch->len) : 0) |
2966 | 0 | + (extra_params ? extra_params->len : 0) + comp_len |
2967 | 0 | + comp_name_len + CRLF_LEN + 1; |
2968 | 0 | line_buf = pkg_malloc(max_len); |
2969 | 0 | if(line_buf == 0) { |
2970 | 0 | ser_error = E_OUT_OF_MEM; |
2971 | 0 | PKG_MEM_ERROR; |
2972 | 0 | return 0; |
2973 | 0 | } |
2974 | | |
2975 | 0 | extra_len = 0; |
2976 | |
|
2977 | 0 | via_len = via_prefix_len + address_str->len; /*space included in MY_VIA*/ |
2978 | |
|
2979 | 0 | memcpy(line_buf, MY_VIA, MY_VIA_LEN); |
2980 | 0 | if(proto == PROTO_UDP) { |
2981 | | /* do nothing */ |
2982 | 0 | } else if(proto == PROTO_TCP) { |
2983 | 0 | memcpy(line_buf + MY_VIA_LEN - 4, "TCP ", 4); |
2984 | 0 | } else if(proto == PROTO_TLS) { |
2985 | 0 | memcpy(line_buf + MY_VIA_LEN - 4, "TLS ", 4); |
2986 | 0 | } else if(proto == PROTO_SCTP) { |
2987 | 0 | memcpy(line_buf + MY_VIA_LEN - 4, "SCTP ", 5); |
2988 | 0 | } else if(proto == PROTO_WS) { |
2989 | 0 | if(unlikely(send_info->send_flags.f & SND_F_FORCE_SOCKET |
2990 | 0 | && send_info->send_sock)) { |
2991 | 0 | local_addr = send_info->send_sock->su; |
2992 | 0 | su_setport(&local_addr, 0); /* any local port will do */ |
2993 | 0 | from = &local_addr; |
2994 | 0 | } |
2995 | |
|
2996 | 0 | port = su_getport(&send_info->to); |
2997 | 0 | if(likely(port)) { |
2998 | 0 | su2ip_addr(&ip, &send_info->to); |
2999 | 0 | con = tcpconn_get(send_info->id, &ip, port, from, 0); |
3000 | 0 | } else if(likely(send_info->id)) |
3001 | 0 | con = tcpconn_get(send_info->id, 0, 0, 0, 0); |
3002 | 0 | else { |
3003 | 0 | LM_CRIT("null_id & to\n"); |
3004 | 0 | pkg_free(line_buf); |
3005 | 0 | return 0; |
3006 | 0 | } |
3007 | | |
3008 | 0 | if(con == NULL) { |
3009 | 0 | LM_WARN("TCP/TLS connection (id: %d) for WebSocket could not be " |
3010 | 0 | "found\n", |
3011 | 0 | send_info->id); |
3012 | 0 | pkg_free(line_buf); |
3013 | 0 | return 0; |
3014 | 0 | } |
3015 | | |
3016 | 0 | if(con->rcv.proto == PROTO_WS) { |
3017 | 0 | memcpy(line_buf + MY_VIA_LEN - 4, "WS ", 3); |
3018 | 0 | } else if(con->rcv.proto == PROTO_WSS) { |
3019 | 0 | memcpy(line_buf + MY_VIA_LEN - 4, "WSS ", 4); |
3020 | 0 | } else { |
3021 | 0 | tcpconn_put(con); |
3022 | 0 | LM_CRIT("unknown proto %d\n", con->rcv.proto); |
3023 | 0 | pkg_free(line_buf); |
3024 | 0 | return 0; |
3025 | 0 | } |
3026 | 0 | tcpconn_put(con); |
3027 | 0 | } else if(proto == PROTO_WSS) { |
3028 | 0 | memcpy(line_buf + MY_VIA_LEN - 4, "WSS ", 4); |
3029 | 0 | } else { |
3030 | 0 | LM_CRIT("unknown proto %d\n", proto); |
3031 | 0 | pkg_free(line_buf); |
3032 | 0 | return 0; |
3033 | 0 | } |
3034 | | /* add [] only if ipv6 address is used; |
3035 | | * if using pre-set no check is made */ |
3036 | 0 | if(send_sock->address.af == AF_INET6) { |
3037 | | /* lightweight safety checks if brackets set |
3038 | | * or non-ipv6 (e.g., advertised hostname) */ |
3039 | 0 | if(address_str->s[0] != '[' |
3040 | 0 | && memchr(address_str->s, ':', address_str->len) != NULL) { |
3041 | 0 | line_buf[via_prefix_len] = '['; |
3042 | 0 | line_buf[via_prefix_len + 1 + address_str->len] = ']'; |
3043 | 0 | extra_len = 1; |
3044 | 0 | via_len += 2; /* [ ]*/ |
3045 | 0 | } |
3046 | 0 | } |
3047 | 0 | memcpy(line_buf + via_prefix_len + extra_len, address_str->s, |
3048 | 0 | address_str->len); |
3049 | 0 | if((send_sock->port_no != SIP_PORT) |
3050 | 0 | || (port_str != &send_sock->port_no_str)) { |
3051 | 0 | line_buf[via_len] = ':'; |
3052 | 0 | via_len++; |
3053 | 0 | memcpy(line_buf + via_len, port_str->s, port_str->len); |
3054 | 0 | via_len += port_str->len; |
3055 | 0 | } |
3056 | | |
3057 | | /* branch parameter */ |
3058 | 0 | if(branch) { |
3059 | 0 | memcpy(line_buf + via_len, MY_BRANCH, MY_BRANCH_LEN); |
3060 | 0 | via_len += MY_BRANCH_LEN; |
3061 | 0 | memcpy(line_buf + via_len, branch->s, branch->len); |
3062 | 0 | via_len += branch->len; |
3063 | 0 | } |
3064 | | /* extra params */ |
3065 | 0 | if(extra_params) { |
3066 | 0 | memcpy(line_buf + via_len, extra_params->s, extra_params->len); |
3067 | 0 | via_len += extra_params->len; |
3068 | 0 | } |
3069 | | #ifdef USE_COMP |
3070 | | /* comp */ |
3071 | | if(comp_len) { |
3072 | | memcpy(line_buf + via_len, COMP_PARAM, COMP_PARAM_LEN); |
3073 | | via_len += COMP_PARAM_LEN; |
3074 | | memcpy(line_buf + via_len, comp_name, comp_name_len); |
3075 | | via_len += comp_name_len; |
3076 | | } |
3077 | | #endif |
3078 | |
|
3079 | 0 | memcpy(line_buf + via_len, CRLF, CRLF_LEN); |
3080 | 0 | via_len += CRLF_LEN; |
3081 | 0 | line_buf[via_len] = 0; /* null terminate the string*/ |
3082 | |
|
3083 | 0 | *len = via_len; |
3084 | 0 | return line_buf; |
3085 | 0 | } |
3086 | | |
3087 | | /* creates a via header honoring the protocol of the incoming socket |
3088 | | * msg is an optional parameter */ |
3089 | | char *create_via_hf(unsigned int *len, struct sip_msg *msg, |
3090 | | struct dest_info *send_info /* where to send the reply */, str *branch) |
3091 | 0 | { |
3092 | 0 | char *via; |
3093 | 0 | str extra_params; |
3094 | 0 | struct hostport hp; |
3095 | 0 | char sbuf[24]; |
3096 | 0 | int slen; |
3097 | 0 | str xparams; |
3098 | 0 | #if defined USE_TCP || defined USE_SCTP |
3099 | 0 | char *id_buf; |
3100 | 0 | unsigned int id_len; |
3101 | | |
3102 | |
|
3103 | 0 | id_buf = 0; |
3104 | 0 | id_len = 0; |
3105 | 0 | #endif |
3106 | 0 | extra_params.len = 0; |
3107 | 0 | extra_params.s = 0; |
3108 | | |
3109 | |
|
3110 | 0 | #if defined USE_TCP || defined USE_SCTP |
3111 | | /* add id if tcp */ |
3112 | 0 | if(msg |
3113 | 0 | && ( |
3114 | 0 | #ifdef USE_TCP |
3115 | 0 | (msg->rcv.proto == PROTO_TCP) |
3116 | 0 | #ifdef USE_TLS |
3117 | 0 | || (msg->rcv.proto == PROTO_TLS) |
3118 | 0 | #endif |
3119 | 0 | #ifdef USE_SCTP |
3120 | 0 | || |
3121 | 0 | #endif /* USE_SCTP */ |
3122 | 0 | #endif /* USE_TCP */ |
3123 | 0 | #ifdef USE_SCTP |
3124 | 0 | (msg->rcv.proto == PROTO_SCTP) |
3125 | 0 | #endif /* USE_SCTP */ |
3126 | 0 | )) { |
3127 | 0 | if((id_buf = id_builder(msg, &id_len)) == 0) { |
3128 | 0 | LM_ERR("id_builder failed\n"); |
3129 | 0 | return 0; /* we don't need to free anything, |
3130 | | nothing alloc'ed yet*/ |
3131 | 0 | } |
3132 | 0 | LM_DBG("id added: <%.*s>, rcv proto=%d\n", (int)id_len, id_buf, |
3133 | 0 | msg->rcv.proto); |
3134 | 0 | extra_params.s = id_buf; |
3135 | 0 | extra_params.len = id_len; |
3136 | 0 | } |
3137 | 0 | #endif /* USE_TCP || USE_SCTP */ |
3138 | | |
3139 | | /* test and add rport parameter to local via - rfc3581 */ |
3140 | 0 | if((ksr_local_rport) || (msg && (msg->msg_flags & FL_ADD_LOCAL_RPORT))) { |
3141 | | /* params so far + ';rport' + '\0' */ |
3142 | 0 | via = (char *)pkg_malloc(extra_params.len + RPORT_LEN); |
3143 | 0 | if(via == 0) { |
3144 | 0 | PKG_MEM_ERROR; |
3145 | 0 | if(extra_params.s) |
3146 | 0 | pkg_free(extra_params.s); |
3147 | 0 | return 0; |
3148 | 0 | } |
3149 | 0 | if(extra_params.s != NULL && extra_params.len > 0) { |
3150 | 0 | memcpy(via, extra_params.s, extra_params.len); |
3151 | 0 | } |
3152 | 0 | if(extra_params.s != NULL) { |
3153 | 0 | pkg_free(extra_params.s); |
3154 | 0 | } |
3155 | 0 | memcpy(via + extra_params.len, RPORT, RPORT_LEN - 1); |
3156 | 0 | extra_params.s = via; |
3157 | 0 | extra_params.len += RPORT_LEN - 1; |
3158 | 0 | extra_params.s[extra_params.len] = '\0'; |
3159 | 0 | } |
3160 | | |
3161 | | /* test and add srvid parameter to local via */ |
3162 | 0 | if(msg && (msg->msg_flags & FL_ADD_SRVID) && server_id != 0) { |
3163 | 0 | slen = snprintf(sbuf, 24, ";srvid=%u", (unsigned int)server_id); |
3164 | 0 | if(slen <= 0 || slen >= 24) { |
3165 | 0 | LM_WARN("failed to build srvid parameter"); |
3166 | 0 | } else { |
3167 | 0 | via = (char *)pkg_malloc(extra_params.len + slen + 1); |
3168 | 0 | if(via == 0) { |
3169 | 0 | PKG_MEM_ERROR; |
3170 | 0 | if(extra_params.s) |
3171 | 0 | pkg_free(extra_params.s); |
3172 | 0 | return 0; |
3173 | 0 | } |
3174 | 0 | if(extra_params.s != NULL && extra_params.len > 0) { |
3175 | 0 | memcpy(via, extra_params.s, extra_params.len); |
3176 | 0 | } |
3177 | 0 | if(extra_params.s != NULL) { |
3178 | 0 | pkg_free(extra_params.s); |
3179 | 0 | } |
3180 | 0 | memcpy(via + extra_params.len, sbuf, slen); |
3181 | 0 | extra_params.s = via; |
3182 | 0 | extra_params.len += slen; |
3183 | 0 | extra_params.s[extra_params.len] = '\0'; |
3184 | 0 | } |
3185 | 0 | } |
3186 | | |
3187 | | /* test and add xavp params */ |
3188 | 0 | if(msg && (msg->msg_flags & FL_ADD_XAVP_VIA_PARAMS) |
3189 | 0 | && _ksr_xavp_via_params.len > 0) { |
3190 | 0 | xparams.s = pv_get_buffer(); |
3191 | 0 | xparams.len = xavp_serialize_fields( |
3192 | 0 | &_ksr_xavp_via_params, xparams.s, pv_get_buffer_size()); |
3193 | 0 | if(xparams.len > 0) { |
3194 | 0 | via = (char *)pkg_malloc(extra_params.len + xparams.len + 2); |
3195 | 0 | if(via == 0) { |
3196 | 0 | PKG_MEM_ERROR; |
3197 | 0 | if(extra_params.s) |
3198 | 0 | pkg_free(extra_params.s); |
3199 | 0 | return 0; |
3200 | 0 | } |
3201 | 0 | if(extra_params.s != NULL && extra_params.len > 0) { |
3202 | 0 | memcpy(via, extra_params.s, extra_params.len); |
3203 | 0 | } |
3204 | 0 | if(extra_params.s != NULL) { |
3205 | 0 | pkg_free(extra_params.s); |
3206 | 0 | } |
3207 | | /* add ';' between via parameters */ |
3208 | 0 | via[extra_params.len] = ';'; |
3209 | | /* skip last ';' from xavp serialized output */ |
3210 | 0 | memcpy(via + extra_params.len + 1, xparams.s, xparams.len - 1); |
3211 | 0 | extra_params.s = via; |
3212 | 0 | extra_params.len += xparams.len; |
3213 | 0 | extra_params.s[extra_params.len] = '\0'; |
3214 | 0 | } |
3215 | 0 | } |
3216 | | |
3217 | 0 | set_hostport(&hp, msg); |
3218 | 0 | via = via_builder(len, msg, send_info, branch, |
3219 | 0 | extra_params.len ? &extra_params : 0, &hp); |
3220 | | |
3221 | | /* we do not need extra_params any more, already in the new via header */ |
3222 | 0 | if(extra_params.s) |
3223 | 0 | pkg_free(extra_params.s); |
3224 | 0 | return via; |
3225 | 0 | } |
3226 | | |
3227 | | /* builds a char* buffer from message headers without body |
3228 | | * first line is excluded in case of skip_first_line=1 |
3229 | | * error is set -1 if the memory allocation fails |
3230 | | */ |
3231 | | char *build_only_headers(struct sip_msg *msg, int skip_first_line, |
3232 | | unsigned int *returned_len, int *error, struct dest_info *send_info) |
3233 | 0 | { |
3234 | 0 | char *buf, *new_buf; |
3235 | 0 | unsigned int offset, s_offset, len, new_len; |
3236 | |
|
3237 | 0 | *error = 0; |
3238 | 0 | buf = msg->buf; |
3239 | 0 | if(skip_first_line) |
3240 | 0 | s_offset = msg->headers->name.s - buf; |
3241 | 0 | else |
3242 | 0 | s_offset = 0; |
3243 | | |
3244 | | /* original length without body, and without final \r\n */ |
3245 | 0 | len = msg->unparsed - buf; |
3246 | | /* new msg length */ |
3247 | 0 | new_len = len - /* original length */ |
3248 | 0 | s_offset + /* skipped first line */ |
3249 | 0 | lumps_len(msg, msg->add_rm, send_info); /* lumps */ |
3250 | |
|
3251 | 0 | if(new_len == 0) { |
3252 | 0 | *returned_len = 0; |
3253 | 0 | return 0; |
3254 | 0 | } |
3255 | | |
3256 | 0 | new_buf = (char *)pkg_malloc(new_len + 1); |
3257 | 0 | if(!new_buf) { |
3258 | 0 | PKG_MEM_ERROR; |
3259 | 0 | *error = -1; |
3260 | 0 | return 0; |
3261 | 0 | } |
3262 | 0 | new_buf[0] = 0; |
3263 | 0 | offset = 0; |
3264 | | |
3265 | | /* copy message lumps */ |
3266 | 0 | process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, |
3267 | 0 | FLAG_MSG_ALL); |
3268 | | /* copy the rest of the message without body */ |
3269 | 0 | if(len > s_offset) { |
3270 | 0 | memcpy(new_buf + offset, buf + s_offset, len - s_offset); |
3271 | 0 | offset += (len - s_offset); |
3272 | 0 | } |
3273 | 0 | new_buf[offset] = 0; |
3274 | |
|
3275 | 0 | *returned_len = offset; |
3276 | 0 | return new_buf; |
3277 | 0 | } |
3278 | | |
3279 | | /* builds a char* buffer from message body |
3280 | | * error is set -1 if the memory allocation fails |
3281 | | */ |
3282 | | char *build_body(struct sip_msg *msg, unsigned int *returned_len, int *error, |
3283 | | struct dest_info *send_info) |
3284 | 0 | { |
3285 | 0 | char *buf, *new_buf, *body; |
3286 | 0 | unsigned int offset, s_offset, len, new_len; |
3287 | |
|
3288 | 0 | *error = 0; |
3289 | 0 | body = get_body(msg); |
3290 | |
|
3291 | 0 | if(!body || (body[0] == 0)) { |
3292 | 0 | *returned_len = 0; |
3293 | 0 | return 0; |
3294 | 0 | } |
3295 | 0 | buf = msg->buf; |
3296 | 0 | s_offset = body - buf; |
3297 | | |
3298 | | /* original length of msg with body */ |
3299 | 0 | len = msg->len; |
3300 | | /* new body length */ |
3301 | 0 | new_len = len - /* original length */ |
3302 | 0 | s_offset + /* msg without body */ |
3303 | 0 | lumps_len(msg, msg->body_lumps, send_info); /* lumps */ |
3304 | |
|
3305 | 0 | new_buf = (char *)pkg_malloc(new_len + 1); |
3306 | 0 | if(!new_buf) { |
3307 | 0 | PKG_MEM_ERROR; |
3308 | 0 | *error = -1; |
3309 | 0 | return 0; |
3310 | 0 | } |
3311 | 0 | new_buf[0] = 0; |
3312 | 0 | offset = 0; |
3313 | | |
3314 | | /* copy body lumps */ |
3315 | 0 | process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info, |
3316 | 0 | FLAG_MSG_ALL); |
3317 | | /* copy the rest of the message without body */ |
3318 | 0 | if(len > s_offset) { |
3319 | 0 | memcpy(new_buf + offset, buf + s_offset, len - s_offset); |
3320 | 0 | offset += (len - s_offset); |
3321 | 0 | } |
3322 | 0 | new_buf[offset] = 0; |
3323 | |
|
3324 | 0 | *returned_len = offset; |
3325 | 0 | return new_buf; |
3326 | 0 | } |
3327 | | |
3328 | | /* builds a char* buffer from SIP message including body |
3329 | | * The function adjusts the Content-Length HF according |
3330 | | * to body lumps in case of touch_clen=1. |
3331 | | */ |
3332 | | char *build_all(struct sip_msg *msg, int touch_clen, unsigned int *returned_len, |
3333 | | int *error, struct dest_info *send_info) |
3334 | 0 | { |
3335 | 0 | char *buf, *new_buf; |
3336 | 0 | unsigned int offset, s_offset, len, new_len; |
3337 | 0 | unsigned int body_delta; |
3338 | |
|
3339 | 0 | *error = 0; |
3340 | | /* Calculate message body difference */ |
3341 | 0 | body_delta = lumps_len(msg, msg->body_lumps, send_info); |
3342 | 0 | if(touch_clen) { |
3343 | | /* adjust Content-Length */ |
3344 | 0 | if(adjust_clen(msg, body_delta, send_info->proto) < 0) { |
3345 | 0 | LM_ERR("Error while adjusting Content-Length\n"); |
3346 | 0 | *error = -1; |
3347 | 0 | return 0; |
3348 | 0 | } |
3349 | 0 | } |
3350 | | |
3351 | 0 | buf = msg->buf; |
3352 | | /* original msg length */ |
3353 | 0 | len = msg->len; |
3354 | | /* new msg length */ |
3355 | 0 | new_len = len + /* original length */ |
3356 | 0 | lumps_len(msg, msg->add_rm, send_info) + /* hdr lumps */ |
3357 | 0 | body_delta; /* body lumps */ |
3358 | |
|
3359 | 0 | if(new_len == 0) { |
3360 | 0 | returned_len = 0; |
3361 | 0 | return 0; |
3362 | 0 | } |
3363 | | |
3364 | 0 | new_buf = (char *)pkg_malloc(new_len + 1); |
3365 | 0 | if(!new_buf) { |
3366 | 0 | PKG_MEM_ERROR; |
3367 | 0 | *error = -1; |
3368 | 0 | return 0; |
3369 | 0 | } |
3370 | 0 | new_buf[0] = 0; |
3371 | 0 | offset = s_offset = 0; |
3372 | | |
3373 | | /* copy message lumps */ |
3374 | 0 | process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, |
3375 | 0 | FLAG_MSG_ALL); |
3376 | | /* copy body lumps */ |
3377 | 0 | process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info, |
3378 | 0 | FLAG_MSG_ALL); |
3379 | | /* copy the rest of the message */ |
3380 | 0 | memcpy(new_buf + offset, buf + s_offset, len - s_offset); |
3381 | 0 | offset += (len - s_offset); |
3382 | 0 | new_buf[offset] = 0; |
3383 | |
|
3384 | 0 | *returned_len = offset; |
3385 | 0 | return new_buf; |
3386 | 0 | } |
3387 | | |
3388 | | |
3389 | | /** |
3390 | | * parse buf in msg and fill several fields |
3391 | | */ |
3392 | | int build_sip_msg_from_buf( |
3393 | | struct sip_msg *msg, char *buf, int len, unsigned int id) |
3394 | 0 | { |
3395 | 0 | if(msg == 0 || buf == 0) |
3396 | 0 | return -1; |
3397 | | |
3398 | 0 | memset(msg, 0, sizeof(sip_msg_t)); |
3399 | 0 | msg->id = id; |
3400 | 0 | msg->pid = my_pid(); |
3401 | 0 | msg->buf = buf; |
3402 | 0 | msg->len = len; |
3403 | 0 | if(parse_msg(buf, len, msg) != 0) { |
3404 | 0 | LM_ERR("parsing failed\n"); |
3405 | 0 | return -1; |
3406 | 0 | } |
3407 | 0 | msg->set_global_address = default_global_address; |
3408 | 0 | msg->set_global_port = default_global_port; |
3409 | 0 | return 0; |
3410 | 0 | } |
3411 | | |
3412 | | /** |
3413 | | * |
3414 | | */ |
3415 | | int sip_msg_update_buffer(sip_msg_t *msg, str *obuf) |
3416 | 0 | { |
3417 | 0 | sip_msg_t tmp; |
3418 | |
|
3419 | 0 | if(obuf == NULL || obuf->s == NULL || obuf->len <= 0) { |
3420 | 0 | LM_ERR("invalid buffer parameter\n"); |
3421 | 0 | return -1; |
3422 | 0 | } |
3423 | 0 | #ifdef USE_TCP |
3424 | 0 | if(tcp_get_clone_rcvbuf() == 0) { |
3425 | 0 | LM_ERR("tcp clone received buffer not enabled\n"); |
3426 | 0 | return -1; |
3427 | 0 | } |
3428 | 0 | #endif |
3429 | 0 | if(obuf->len >= BUF_SIZE) { |
3430 | 0 | LM_ERR("new buffer is too large (%d)\n", obuf->len); |
3431 | 0 | return -1; |
3432 | 0 | } |
3433 | | /* temporary copy */ |
3434 | 0 | memcpy(&tmp, msg, sizeof(sip_msg_t)); |
3435 | | |
3436 | | /* reset dst uri and path vector to avoid freeing - restored later */ |
3437 | 0 | if(msg->dst_uri.s != NULL) { |
3438 | 0 | msg->dst_uri.s = NULL; |
3439 | 0 | msg->dst_uri.len = 0; |
3440 | 0 | } |
3441 | 0 | if(msg->path_vec.s != NULL) { |
3442 | 0 | msg->path_vec.s = NULL; |
3443 | 0 | msg->path_vec.len = 0; |
3444 | 0 | } |
3445 | | |
3446 | | /* free old msg structure */ |
3447 | 0 | free_sip_msg(msg); |
3448 | 0 | memset(msg, 0, sizeof(sip_msg_t)); |
3449 | | |
3450 | | /* restore msg fields */ |
3451 | 0 | msg->buf = tmp.buf; |
3452 | 0 | msg->id = tmp.id; |
3453 | 0 | msg->pid = tmp.pid; |
3454 | 0 | msg->rcv = tmp.rcv; |
3455 | 0 | msg->set_global_address = tmp.set_global_address; |
3456 | 0 | msg->set_global_port = tmp.set_global_port; |
3457 | 0 | msg->flags = tmp.flags; |
3458 | 0 | msg->msg_flags = tmp.msg_flags; |
3459 | 0 | memcpy(msg->xflags, tmp.xflags, KSR_XFLAGS_SIZE * sizeof(flag_t)); |
3460 | 0 | msg->hash_index = tmp.hash_index; |
3461 | 0 | msg->force_send_socket = tmp.force_send_socket; |
3462 | 0 | msg->fwd_send_flags = tmp.fwd_send_flags; |
3463 | 0 | msg->rpl_send_flags = tmp.rpl_send_flags; |
3464 | 0 | msg->dst_uri = tmp.dst_uri; |
3465 | 0 | msg->path_vec = tmp.path_vec; |
3466 | |
|
3467 | 0 | memcpy(msg->buf, obuf->s, obuf->len); |
3468 | 0 | msg->len = obuf->len; |
3469 | 0 | msg->buf[msg->len] = '\0'; |
3470 | | |
3471 | | /* reparse the message */ |
3472 | 0 | LM_DBG("SIP message content updated - reparsing\n"); |
3473 | 0 | if(parse_msg(msg->buf, msg->len, msg) != 0) { |
3474 | 0 | LM_ERR("parsing new sip message failed [[%.*s]]\n", msg->len, msg->buf); |
3475 | | /* exit config execution - sip_msg_t structure is no longer |
3476 | | * valid/safe for config */ |
3477 | 0 | return 0; |
3478 | 0 | } |
3479 | 0 | if(parse_headers(msg, HDR_FROM_F | HDR_TO_F | HDR_CALLID_F | HDR_CSEQ_F, 0) |
3480 | 0 | < 0) { |
3481 | 0 | LM_ERR("parsing main headers of new sip message failed [[%.*s]]\n", |
3482 | 0 | msg->len, msg->buf); |
3483 | | /* exit config execution - sip_msg_t structure is no longer |
3484 | | * valid/safe for config */ |
3485 | 0 | return 0; |
3486 | 0 | } |
3487 | 0 | return 1; |
3488 | 0 | } |
3489 | | |
3490 | | /** |
3491 | | * |
3492 | | */ |
3493 | | int sip_msg_apply_changes(sip_msg_t *msg) |
3494 | 0 | { |
3495 | 0 | int ret; |
3496 | 0 | dest_info_t dst; |
3497 | 0 | str obuf; |
3498 | |
|
3499 | 0 | if(msg->first_line.type != SIP_REPLY && get_route_type() != REQUEST_ROUTE) { |
3500 | 0 | LM_ERR("invalid usage - not in request route or a reply\n"); |
3501 | 0 | return -1; |
3502 | 0 | } |
3503 | | |
3504 | 0 | init_dest_info(&dst); |
3505 | 0 | dst.proto = PROTO_UDP; |
3506 | 0 | if(msg->first_line.type == SIP_REPLY) { |
3507 | 0 | obuf.s = generate_res_buf_from_sip_res( |
3508 | 0 | msg, (unsigned int *)&obuf.len, BUILD_NO_VIA1_UPDATE); |
3509 | 0 | } else { |
3510 | 0 | if(msg->msg_flags & FL_RR_ADDED) { |
3511 | 0 | LM_ERR("cannot apply msg changes after adding record-route" |
3512 | 0 | " header - it breaks conditional 2nd header\n"); |
3513 | 0 | return -1; |
3514 | 0 | } |
3515 | 0 | obuf.s = build_req_buf_from_sip_req(msg, (unsigned int *)&obuf.len, |
3516 | 0 | &dst, |
3517 | 0 | BUILD_NO_PATH | BUILD_NO_LOCAL_VIA | BUILD_NO_VIA1_UPDATE); |
3518 | 0 | } |
3519 | 0 | if(obuf.s == NULL) { |
3520 | 0 | LM_ERR("couldn't update msg buffer content\n"); |
3521 | 0 | return -1; |
3522 | 0 | } |
3523 | 0 | ret = sip_msg_update_buffer(msg, &obuf); |
3524 | | /* free new buffer - copied in the static buffer from old sip_msg_t */ |
3525 | 0 | pkg_free(obuf.s); |
3526 | |
|
3527 | 0 | return ret; |
3528 | 0 | } |