- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)
1 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,863 +0,0 @@ |
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 |
- * \file |
|
24 |
- * \brief Kamailio core :: Message forwarding |
|
25 |
- * \ingroup core |
|
26 |
- * Module: \ref core |
|
27 |
- */ |
|
28 |
- |
|
29 |
- |
|
30 |
- |
|
31 |
-#include <string.h> |
|
32 |
-#include <stdio.h> |
|
33 |
-#include <stdlib.h> |
|
34 |
-#include <sys/types.h> |
|
35 |
-#include <sys/socket.h> |
|
36 |
-#include <netdb.h> |
|
37 |
-#include <netinet/in.h> |
|
38 |
-#include <arpa/inet.h> |
|
39 |
- |
|
40 |
-#include "forward.h" |
|
41 |
-#include "hash_func.h" |
|
42 |
-#include "config.h" |
|
43 |
-#include "parser/msg_parser.h" |
|
44 |
-#include "char_msg_val.h" |
|
45 |
-#include "route.h" |
|
46 |
-#include "events.h" |
|
47 |
-#include "dprint.h" |
|
48 |
-#include "globals.h" |
|
49 |
-#include "cfg_core.h" |
|
50 |
-#include "data_lump.h" |
|
51 |
-#include "ut.h" |
|
52 |
-#include "mem/mem.h" |
|
53 |
-#include "msg_translator.h" |
|
54 |
-#include "sr_module.h" |
|
55 |
-#include "ip_addr.h" |
|
56 |
-#include "resolve.h" |
|
57 |
-#include "name_alias.h" |
|
58 |
-#include "socket_info.h" |
|
59 |
-#include "onsend.h" |
|
60 |
-#include "resolve.h" |
|
61 |
-#ifdef USE_DNS_FAILOVER |
|
62 |
-#include "dns_cache.h" |
|
63 |
-#endif |
|
64 |
-#ifdef USE_DST_BLACKLIST |
|
65 |
-#include "dst_blacklist.h" |
|
66 |
-#endif |
|
67 |
-#include "compiler_opt.h" |
|
68 |
-#include "core_stats.h" |
|
69 |
- |
|
70 |
-#ifdef DEBUG_DMALLOC |
|
71 |
-#include <dmalloc.h> |
|
72 |
-#endif |
|
73 |
- |
|
74 |
- |
|
75 |
- |
|
76 |
-/* return a socket_info_pointer to the sending socket; as opposed to |
|
77 |
- * get_send_socket, which returns process's default socket, get_out_socket |
|
78 |
- * attempts to determine the outbound interface which will be used; |
|
79 |
- * it uses a temporary connected socket to determine it; it will |
|
80 |
- * be very likely noticeably slower, but it can deal better with |
|
81 |
- * multihomed hosts |
|
82 |
- */ |
|
83 |
- |
|
84 |
-static int mhomed_sock_cache_disabled = 0; |
|
85 |
-static int sock_inet = -1; |
|
86 |
-static int sock_inet6 = -1; |
|
87 |
-static int _forward_set_send_info = 0; |
|
88 |
- |
|
89 |
-void forward_set_send_info(int v) |
|
90 |
-{ |
|
91 |
- _forward_set_send_info = v; |
|
92 |
-} |
|
93 |
- |
|
94 |
-static void apply_force_send_socket(struct dest_info* dst, struct sip_msg* msg); |
|
95 |
- |
|
96 |
-struct socket_info* get_out_socket(union sockaddr_union* to, int proto) |
|
97 |
-{ |
|
98 |
- int* temp_sock; |
|
99 |
- socklen_t len; |
|
100 |
- union sockaddr_union from; |
|
101 |
- struct socket_info* si; |
|
102 |
- struct ip_addr ip; |
|
103 |
- union sockaddr_union uncon; |
|
104 |
- |
|
105 |
- memset(&uncon, 0, sizeof(union sockaddr_union)); |
|
106 |
- uncon.sin.sin_family = AF_UNSPEC; |
|
107 |
- |
|
108 |
- if (unlikely(proto!=PROTO_UDP)) { |
|
109 |
- LM_CRIT("can only be called for UDP\n"); |
|
110 |
- return 0; |
|
111 |
- } |
|
112 |
-retry: |
|
113 |
- switch(to->s.sa_family){ |
|
114 |
- case AF_INET : { |
|
115 |
- if(unlikely(sock_inet < 0)){ |
|
116 |
- sock_inet = socket(AF_INET, SOCK_DGRAM, 0); |
|
117 |
- if (sock_inet==-1) { |
|
118 |
- LM_ERR("socket() failed: %s\n", strerror(errno)); |
|
119 |
- return 0; |
|
120 |
- } |
|
121 |
- } |
|
122 |
- temp_sock = &sock_inet; |
|
123 |
- break; |
|
124 |
- } |
|
125 |
- case AF_INET6 : { |
|
126 |
- if(unlikely(sock_inet6 < 0)){ |
|
127 |
- sock_inet6 = socket(AF_INET6, SOCK_DGRAM, 0); |
|
128 |
- if (sock_inet6==-1) { |
|
129 |
- LM_ERR("socket() failed: %s\n", strerror(errno)); |
|
130 |
- return 0; |
|
131 |
- } |
|
132 |
- } |
|
133 |
- temp_sock = &sock_inet6; |
|
134 |
- break; |
|
135 |
- } |
|
136 |
- default: { |
|
137 |
- LM_ERR("Unknown protocol family \n"); |
|
138 |
- return 0; |
|
139 |
- } |
|
140 |
- } |
|
141 |
- |
|
142 |
- if( !mhomed_sock_cache_disabled ){ |
|
143 |
- /* some Linux kernel versions (all?) along with other UNIXes don't re-bound the sock if already bound */ |
|
144 |
- /* to un-bound a socket set sin_family to AF_UNSPEC and zero out the rest*/ |
|
145 |
- if (unlikely(connect(*temp_sock, &uncon.s, sockaddru_len(uncon)) < 0)) |
|
146 |
- mhomed_sock_cache_disabled = 1; |
|
147 |
- } |
|
148 |
- |
|
149 |
- if (unlikely(connect(*temp_sock, &to->s, sockaddru_len(*to))==-1)) { |
|
150 |
- if (unlikely(errno==EISCONN && !mhomed_sock_cache_disabled)){ |
|
151 |
- /* no multiple connects support on the same socket */ |
|
152 |
- mhomed_sock_cache_disabled=1; |
|
153 |
- if (sock_inet>=0){ |
|
154 |
- close(sock_inet); |
|
155 |
- sock_inet=-1; |
|
156 |
- } |
|
157 |
- if (sock_inet6>=0){ |
|
158 |
- close(sock_inet6); |
|
159 |
- sock_inet6=-1; |
|
160 |
- } |
|
161 |
- goto retry; |
|
162 |
- } |
|
163 |
- LM_ERR("connect failed: %s\n", strerror(errno)); |
|
164 |
- goto error; |
|
165 |
- } |
|
166 |
- len=sizeof(from); |
|
167 |
- if (unlikely(getsockname(*temp_sock, &from.s, &len)==-1)) { |
|
168 |
- LM_ERR("getsockname failed: %s\n", strerror(errno)); |
|
169 |
- goto error; |
|
170 |
- } |
|
171 |
- su2ip_addr(&ip, &from); |
|
172 |
- si=find_si(&ip, 0, proto); |
|
173 |
- if (si==0) goto error; |
|
174 |
- LM_DBG("socket determined: %p\n", si ); |
|
175 |
- if (unlikely(mhomed_sock_cache_disabled)){ |
|
176 |
- close(*temp_sock); |
|
177 |
- *temp_sock=-1; |
|
178 |
- } |
|
179 |
- return si; |
|
180 |
-error: |
|
181 |
- LM_ERR("no socket found\n"); |
|
182 |
- ERR("no corresponding socket found for(%s:%s)\n", |
|
183 |
- proto2a(proto), su2a(to, sizeof(*to))); |
|
184 |
- if (unlikely(mhomed_sock_cache_disabled && *temp_sock >=0)){ |
|
185 |
- close(*temp_sock); |
|
186 |
- *temp_sock=-1; |
|
187 |
- } |
|
188 |
- return 0; |
|
189 |
-} |
|
190 |
- |
|
191 |
- |
|
192 |
- |
|
193 |
-/** get the sending socket for a corresponding destination. |
|
194 |
- * @param force_send_socket - if !=0 and the protocol and af correspond |
|
195 |
- * with the destination, it will be returned. |
|
196 |
- * If the protocol or af check fail, a look-alike |
|
197 |
- * socket will be searched for and mismatch will be |
|
198 |
- * set. If no look-alike socket is found it will |
|
199 |
- * fallback to normal resolution. |
|
200 |
- * @param to - destination |
|
201 |
- * @param proto - protocol |
|
202 |
- * @param mismatch - result parameter, set if a force_send_socket was used, but |
|
203 |
- * there was an error matching it exactly to the destination. |
|
204 |
- * Possible values: 0 ok, SS_MISMATCH_PROTO, |
|
205 |
- * SS_MISMATCH_ADDR, SS_MISMATCH_AF, SS_MISMATCH_MCAST. |
|
206 |
- * @return a socket_info pointer to the sending socket on success (and possibly |
|
207 |
- * sets mismatch) or 0 on error. |
|
208 |
- */ |
|
209 |
-struct socket_info* get_send_socket2(struct socket_info* force_send_socket, |
|
210 |
- union sockaddr_union* to, int proto, |
|
211 |
- enum ss_mismatch* mismatch) |
|
212 |
-{ |
|
213 |
- struct socket_info* send_sock; |
|
214 |
- struct socket_info* orig; |
|
215 |
- |
|
216 |
- if (likely(mismatch)) *mismatch=0; |
|
217 |
- /* check if send interface is not forced */ |
|
218 |
- if (unlikely(force_send_socket)){ |
|
219 |
- orig=force_send_socket; |
|
220 |
- /* Special case here as there is no ;transport=wss - so wss connections will |
|
221 |
- appear as ws ones and be sorted out in the WebSocket module */ |
|
222 |
- if (unlikely(orig->proto!=proto && !(orig->proto==PROTO_TLS && proto==PROTO_WS))){ |
|
223 |
- force_send_socket=find_si(&(force_send_socket->address), |
|
224 |
- force_send_socket->port_no, |
|
225 |
- proto); |
|
226 |
- if (unlikely(force_send_socket == 0)){ |
|
227 |
- if (likely(mismatch)) *mismatch=SS_MISMATCH_ADDR; |
|
228 |
- LM_WARN("protocol/port mismatch (forced %s:%s:%d, to %s:%s)\n", |
|
229 |
- proto2a(orig->proto), ip_addr2a(&orig->address), |
|
230 |
- orig->port_no, |
|
231 |
- proto2a(proto), su2a(to, sizeof(*to))); |
|
232 |
- goto not_forced; |
|
233 |
- } |
|
234 |
- if (likely(mismatch)) *mismatch=SS_MISMATCH_PROTO; |
|
235 |
- } |
|
236 |
- if (unlikely(force_send_socket->address.af!=to->s.sa_family)){ |
|
237 |
- LM_DBG("force_send_socket of different af" |
|
238 |
- " (dst %d - %s:%s forced %d -%s:%s:%d)\n", |
|
239 |
- to->s.sa_family, proto2a(proto), su2a(to, sizeof(*to)), |
|
240 |
- force_send_socket->address.af, |
|
241 |
- proto2a(force_send_socket->proto), |
|
242 |
- ip_addr2a(&force_send_socket->address), |
|
243 |
- force_send_socket->port_no); |
|
244 |
- if (likely(mismatch)) *mismatch=SS_MISMATCH_AF; |
|
245 |
- goto not_forced; |
|
246 |
- } |
|
247 |
- /* check if listening on the socket (the check does not work |
|
248 |
- for TCP and TLS, for them socket==-1 on all the processes |
|
249 |
- except tcp_main(), see close_extra_socks() */ |
|
250 |
- if (likely((force_send_socket->socket!=-1 || |
|
251 |
- force_send_socket->proto==PROTO_TCP || |
|
252 |
- force_send_socket->proto==PROTO_TLS || |
|
253 |
- force_send_socket->proto==PROTO_WS || |
|
254 |
- force_send_socket->proto==PROTO_WSS) && |
|
255 |
- !(force_send_socket->flags & SI_IS_MCAST))) |
|
256 |
- return force_send_socket; |
|
257 |
- else{ |
|
258 |
- if (!(force_send_socket->flags & SI_IS_MCAST)) |
|
259 |
- LM_WARN("not listening on the requested socket (%s:%s:%d)," |
|
260 |
- " no fork mode?\n", |
|
261 |
- proto2a(force_send_socket->proto), |
|
262 |
- ip_addr2a(&force_send_socket->address), |
|
263 |
- force_send_socket->port_no); |
|
264 |
- else if (likely(mismatch)) *mismatch=SS_MISMATCH_MCAST; |
|
265 |
- } |
|
266 |
- }; |
|
267 |
-not_forced: |
|
268 |
- if (mhomed && proto==PROTO_UDP){ |
|
269 |
- send_sock=get_out_socket(to, proto); |
|
270 |
- if ((send_sock==0) || (send_sock->socket!=-1)) |
|
271 |
- return send_sock; /* found or error*/ |
|
272 |
- else if (send_sock->socket==-1){ |
|
273 |
- LM_WARN("not listening on the" |
|
274 |
- " requested socket (%s:%s:%d), no fork mode?\n", |
|
275 |
- proto2a(send_sock->proto), ip_addr2a(&send_sock->address), |
|
276 |
- send_sock->port_no); |
|
277 |
- /* continue: try to use some socket */ |
|
278 |
- } |
|
279 |
- } |
|
280 |
- |
|
281 |
- send_sock=0; |
|
282 |
- /* check if we need to change the socket (different address families - |
|
283 |
- * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */ |
|
284 |
- switch(proto){ |
|
285 |
-#ifdef USE_TCP |
|
286 |
- case PROTO_WS: |
|
287 |
- case PROTO_TCP: |
|
288 |
- /* on tcp just use the "main address", we don't really now the |
|
289 |
- * sending address (we can find it out, but we'll need also to see |
|
290 |
- * if we listen on it, and if yes on which port -> too complicated*/ |
|
291 |
- switch(to->s.sa_family){ |
|
292 |
- /* FIXME */ |
|
293 |
- case AF_INET: send_sock=sendipv4_tcp; |
|
294 |
- break; |
|
295 |
- case AF_INET6: send_sock=sendipv6_tcp; |
|
296 |
- break; |
|
297 |
- default: LM_ERR("don't know how to forward to af %d\n", |
|
298 |
- to->s.sa_family); |
|
299 |
- } |
|
300 |
- break; |
|
301 |
-#endif |
|
302 |
-#ifdef USE_TLS |
|
303 |
- case PROTO_WSS: |
|
304 |
- case PROTO_TLS: |
|
305 |
- switch(to->s.sa_family){ |
|
306 |
- /* FIXME */ |
|
307 |
- case AF_INET: send_sock=sendipv4_tls; |
|
308 |
- break; |
|
309 |
- case AF_INET6: send_sock=sendipv6_tls; |
|
310 |
- break; |
|
311 |
- default: LM_ERR("don't know how to forward to af %d\n", |
|
312 |
- to->s.sa_family); |
|
313 |
- } |
|
314 |
- break; |
|
315 |
-#endif /* USE_TLS */ |
|
316 |
-#ifdef USE_SCTP |
|
317 |
- case PROTO_SCTP: |
|
318 |
- if ((bind_address==0) || |
|
319 |
- (to->s.sa_family!=bind_address->address.af) || |
|
320 |
- (bind_address->proto!=PROTO_SCTP)){ |
|
321 |
- switch(to->s.sa_family){ |
|
322 |
- case AF_INET: send_sock=sendipv4_sctp; |
|
323 |
- break; |
|
324 |
- case AF_INET6: send_sock=sendipv6_sctp; |
|
325 |
- break; |
|
326 |
- default: LM_ERR("don't know how to forward to af %d\n", |
|
327 |
- to->s.sa_family); |
|
328 |
- } |
|
329 |
- }else send_sock=bind_address; |
|
330 |
- break; |
|
331 |
-#endif /* USE_SCTP */ |
|
332 |
- case PROTO_UDP: |
|
333 |
- if ((bind_address==0) || |
|
334 |
- (to->s.sa_family!=bind_address->address.af) || |
|
335 |
- (bind_address->proto!=PROTO_UDP)){ |
|
336 |
- switch(to->s.sa_family){ |
|
337 |
- case AF_INET: send_sock=sendipv4; |
|
338 |
- break; |
|
339 |
- case AF_INET6: send_sock=sendipv6; |
|
340 |
- break; |
|
341 |
- default: LM_ERR("don't know how to forward to af %d\n", |
|
342 |
- to->s.sa_family); |
|
343 |
- } |
|
344 |
- }else send_sock=bind_address; |
|
345 |
- break; |
|
346 |
- default: |
|
347 |
- LM_CRIT("unsupported proto %d (%s)\n", proto, proto2a(proto)); |
|
348 |
- } |
|
349 |
- return send_sock; |
|
350 |
-} |
|
351 |
- |
|
352 |
-static struct _check_self_func { |
|
353 |
- check_self_f fself; |
|
354 |
- struct _check_self_func *next; |
|
355 |
-} *_check_self_func_list = NULL; |
|
356 |
- |
|
357 |
-/** check if _check_self_func_list is set |
|
358 |
- * - return 1 if yes, 0 if no |
|
359 |
- */ |
|
360 |
-int is_check_self_func_list_set(void) |
|
361 |
-{ |
|
362 |
- return (_check_self_func_list)?1:0; |
|
363 |
-} |
|
364 |
- |
|
365 |
-/** register a function to be called when matching for myself |
|
366 |
- * - return 0 on success, -1 on error |
|
367 |
- * - f must have same prototype as check_self() and return same kind of values |
|
368 |
- */ |
|
369 |
-int register_check_self_func(check_self_f f) |
|
370 |
-{ |
|
371 |
- struct _check_self_func *nf = 0; |
|
372 |
- nf=(struct _check_self_func*)pkg_malloc(sizeof(struct _check_self_func)); |
|
373 |
- if(nf==0) |
|
374 |
- { |
|
375 |
- LM_ERR("no more pkg\n"); |
|
376 |
- return -1; |
|
377 |
- } |
|
378 |
- nf->fself = f; |
|
379 |
- nf->next = _check_self_func_list; |
|
380 |
- _check_self_func_list = nf; |
|
381 |
- return 0; |
|
382 |
-} |
|
383 |
- |
|
384 |
-/** run registered check self functions |
|
385 |
- * returns 1 if true, 0 if false |
|
386 |
- */ |
|
387 |
-int run_check_self_func(str* host, unsigned short port, unsigned short proto) |
|
388 |
-{ |
|
389 |
- struct _check_self_func *sf = 0; |
|
390 |
- |
|
391 |
- if(_check_self_func_list==NULL) |
|
392 |
- return 0; |
|
393 |
- for(sf=_check_self_func_list; sf; sf=sf->next) |
|
394 |
- if(sf->fself(host, port, proto)==1) |
|
395 |
- return 1; |
|
396 |
- return 0; |
|
397 |
-} |
|
398 |
- |
|
399 |
-/** checks if the proto: host:port is one of the address we listen on; |
|
400 |
- * |
|
401 |
- * if port==0, the port number is ignored |
|
402 |
- * if proto==0 (PROTO_NONE) the protocol is ignored |
|
403 |
- * returns 1 if true, 0 if false, -1 on error |
|
404 |
- * WARNING: uses str2ip6 so it will overwrite any previous |
|
405 |
- * unsaved result of this function (static buffer) |
|
406 |
- */ |
|
407 |
-int check_self(str* host, unsigned short port, unsigned short proto) |
|
408 |
-{ |
|
409 |
- if (grep_sock_info(host, port, proto)) goto found; |
|
410 |
- /* try to look into the aliases*/ |
|
411 |
- if (grep_aliases(host->s, host->len, port, proto)==0){ |
|
412 |
- LM_DBG("host != me\n"); |
|
413 |
- return (_check_self_func_list==NULL)?0:run_check_self_func(host, |
|
414 |
- port, proto); |
|
415 |
- } |
|
416 |
-found: |
|
417 |
- return 1; |
|
418 |
-} |
|
419 |
- |
|
420 |
-/** checks if the proto:port is one of the ports we listen on; |
|
421 |
- * if proto==0 (PROTO_NONE) the protocol is ignored |
|
422 |
- * returns 1 if true, 0 if false, -1 on error |
|
423 |
- */ |
|
424 |
-int check_self_port(unsigned short port, unsigned short proto) |
|
425 |
-{ |
|
426 |
- if (grep_sock_info_by_port(port, proto)) |
|
427 |
- /* as aliases do not contain different ports we can skip them */ |
|
428 |
- return 1; |
|
429 |
- else |
|
430 |
- return 0; |
|
431 |
-} |
|
432 |
- |
|
433 |
- |
|
434 |
- |
|
435 |
-/** forwards a request to dst |
|
436 |
- * parameters: |
|
437 |
- * msg - sip msg |
|
438 |
- * dst - destination name, if non-null it will be resolved and |
|
439 |
- * send_info updated with the ip/port. Even if dst is non |
|
440 |
- * null send_info must contain the protocol and if a non |
|
441 |
- * default port or non srv. lookup is desired, the port must |
|
442 |
- * be !=0 |
|
443 |
- * port - used only if dst!=0 (else the port in send_info->to is used) |
|
444 |
- * send_info - value/result partially filled dest_info structure: |
|
445 |
- * - send_info->proto and comp are used |
|
446 |
- * - send_info->to will be filled (dns) |
|
447 |
- * - send_info->send_flags is filled from the message |
|
448 |
- * - if the send_socket member is null, a send_socket will be |
|
449 |
- * chosen automatically |
|
450 |
- * WARNING: don't forget to zero-fill all the unused members (a non-zero |
|
451 |
- * random id along with proto==PROTO_TCP can have bad consequences, same for |
|
452 |
- * a bogus send_socket value) |
|
453 |
- */ |
|
454 |
-int forward_request(struct sip_msg* msg, str* dst, unsigned short port, |
|
455 |
- struct dest_info* send_info) |
|
456 |
-{ |
|
457 |
- unsigned int len; |
|
458 |
- char* buf; |
|
459 |
- char md5[MD5_LEN]; |
|
460 |
- struct socket_info* orig_send_sock; /* initial send_sock */ |
|
461 |
- int ret; |
|
462 |
- struct ip_addr ip; /* debugging only */ |
|
463 |
- char proto; |
|
464 |
- struct onsend_info onsnd_info = {0}; |
|
465 |
-#ifdef USE_DNS_FAILOVER |
|
466 |
- struct socket_info* prev_send_sock; |
|
467 |
- int err; |
|
468 |
- struct dns_srv_handle dns_srv_h; |
|
469 |
- |
|
470 |
- prev_send_sock=0; |
|
471 |
- err=0; |
|
472 |
-#endif |
|
473 |
- |
|
474 |
- |
|
475 |
- buf=0; |
|
476 |
- orig_send_sock=send_info->send_sock; |
|
477 |
- proto=send_info->proto; |
|
478 |
- ret=0; |
|
479 |
- |
|
480 |
- if(dst){ |
|
481 |
-#ifdef USE_DNS_FAILOVER |
|
482 |
- if (cfg_get(core, core_cfg, use_dns_failover)){ |
|
483 |
- dns_srv_handle_init(&dns_srv_h); |
|
484 |
- err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port, |
|
485 |
- &proto, dns_flags); |
|
486 |
- if (err!=0){ |
|
487 |
- LM_ERR("resolving \"%.*s\" failed: %s [%d]\n", |
|
488 |
- dst->len, ZSW(dst->s), dns_strerror(err), err); |
|
489 |
- ret=E_BAD_ADDRESS; |
|
490 |
- goto error; |
|
491 |
- } |
|
492 |
- }else |
|
493 |
-#endif |
|
494 |
- if (sip_hostport2su(&send_info->to, dst, port, &proto)<0){ |
|
495 |
- LM_ERR("bad host name %.*s, dropping packet\n", dst->len, ZSW(dst->s)); |
|
496 |
- ret=E_BAD_ADDRESS; |
|
497 |
- goto error; |
|
498 |
- } |
|
499 |
- }/* dst */ |
|
500 |
- send_info->send_flags=msg->fwd_send_flags; |
|
501 |
- /* calculate branch for outbound request; |
|
502 |
- calculate is from transaction key, i.e., as an md5 of From/To/CallID/ |
|
503 |
- CSeq exactly the same way as TM does; good for reboot -- than messages |
|
504 |
- belonging to transaction lost due to reboot will still be forwarded |
|
505 |
- with the same branch parameter and will be match-able downstream |
|
506 |
- */ |
|
507 |
- if (!char_msg_val( msg, md5 )) { /* parses transaction key */ |
|
508 |
- LM_ERR("char_msg_val failed\n"); |
|
509 |
- ret=E_UNSPEC; |
|
510 |
- goto error; |
|
511 |
- } |
|
512 |
- msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number); |
|
513 |
- if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */, |
|
514 |
- msg->add_to_branch_s, &msg->add_to_branch_len )) { |
|
515 |
- LM_ERR("branch_builder failed\n"); |
|
516 |
- ret=E_UNSPEC; |
|
517 |
- goto error; |
|
518 |
- } |
|
519 |
- /* try to send the message until success or all the ips are exhausted |
|
520 |
- * (if dns lookup is performed && the dns cache used ) */ |
|
521 |
-#ifdef USE_DNS_FAILOVER |
|
522 |
- do{ |
|
523 |
-#endif |
|
524 |
- if (orig_send_sock==0) /* no forced send_sock => find it **/ |
|
525 |
- send_info->send_sock=get_send_socket(msg, &send_info->to, proto); |
|
526 |
- if (send_info->send_sock==0){ |
|
527 |
- LM_ERR("cannot forward to af %d, proto %d " |
|
528 |
- "no corresponding listening socket\n", |
|
529 |
- send_info->to.s.sa_family, proto); |
|
530 |
- ret=ser_error=E_NO_SOCKET; |
|
531 |
-#ifdef USE_DNS_FAILOVER |
|
532 |
- /* continue, maybe we find a socket for some other ip */ |
|
533 |
- continue; |
|
534 |
-#else |
|
535 |
- goto error; |
|
536 |
-#endif |
|
537 |
- } |
|
538 |
- |
|
539 |
-#ifdef USE_DNS_FAILOVER |
|
540 |
- if (prev_send_sock!=send_info->send_sock){ |
|
541 |
- /* rebuild the message only if the send_sock changed */ |
|
542 |
- prev_send_sock=send_info->send_sock; |
|
543 |
-#endif |
|
544 |
- if (buf) pkg_free(buf); |
|
545 |
- send_info->proto=proto; |
|
546 |
- buf = build_req_buf_from_sip_req(msg, &len, send_info, 0); |
|
547 |
- if (!buf){ |
|
548 |
- LM_ERR("building failed\n"); |
|
549 |
- ret=E_OUT_OF_MEM; /* most probable */ |
|
550 |
- goto error; |
|
551 |
- } |
|
552 |
-#ifdef USE_DNS_FAILOVER |
|
553 |
- } |
|
554 |
-#endif |
|
555 |
- /* send it! */ |
|
556 |
- LM_DBG("Sending:\n%.*s.\n", (int)len, buf); |
|
557 |
- LM_DBG("orig. len=%d, new_len=%d, proto=%d\n", |
|
558 |
- msg->len, len, send_info->proto ); |
|
559 |
- |
|
560 |
- if (run_onsend(msg, send_info, buf, len)==0){ |
|
561 |
- su2ip_addr(&ip, &send_info->to); |
|
562 |
- LM_INFO("request to %s:%d(%d) dropped (onsend_route)\n", |
|
563 |
- ip_addr2a(&ip), su_getport(&send_info->to), send_info->proto); |
|
564 |
- ser_error=E_OK; /* no error */ |
|
565 |
- ret=E_ADM_PROHIBITED; |
|
566 |
-#ifdef USE_DNS_FAILOVER |
|
567 |
- continue; /* try another ip */ |
|
568 |
-#else |
|
569 |
- goto error; /* error ? */ |
|
570 |
-#endif |
|
571 |
- } |
|
572 |
-#ifdef USE_DST_BLACKLIST |
|
573 |
- if (cfg_get(core, core_cfg, use_dst_blacklist)){ |
|
574 |
- if (dst_is_blacklisted(send_info, msg)){ |
|
575 |
- su2ip_addr(&ip, &send_info->to); |
|
576 |
- LM_DBG("blacklisted destination:%s:%d (%d)\n", |
|
577 |
- ip_addr2a(&ip), su_getport(&send_info->to), send_info->proto); |
|
578 |
- ret=ser_error=E_SEND; |
|
579 |
-#ifdef USE_DNS_FAILOVER |
|
580 |
- continue; /* try another ip */ |
|
581 |
-#else |
|
582 |
- goto error; |
|
583 |
-#endif |
|
584 |
- } |
|
585 |
- } |
|
586 |
-#endif |
|
587 |
- |
|
588 |
- if(unlikely(_forward_set_send_info==1)) { |
|
589 |
- onsnd_info.to=&send_info->to; |
|
590 |
- onsnd_info.send_sock=send_info->send_sock; |
|
591 |
- onsnd_info.buf=buf; |
|
592 |
- onsnd_info.len=len; |
|
593 |
- onsnd_info.msg=msg; |
|
594 |
- p_onsend=&onsnd_info; |
|
595 |
- } |
|
596 |
- |
|
597 |
- if (msg_send(send_info, buf, len)<0){ |
|
598 |
- p_onsend=0; |
|
599 |
- ret=ser_error=E_SEND; |
|
600 |
-#ifdef USE_DST_BLACKLIST |
|
601 |
- (void)dst_blacklist_add(BLST_ERR_SEND, send_info, msg); |
|
602 |
-#endif |
|
603 |
-#ifdef USE_DNS_FAILOVER |
|
604 |
- continue; /* try another ip */ |
|
605 |
-#else |
|
606 |
- goto error; |
|
607 |
-#endif |
|
608 |
- }else{ |
|
609 |
- p_onsend=0; |
|
610 |
- ret=ser_error=E_OK; |
|
611 |
- /* sent requests stats */ |
|
612 |
- STATS_TX_REQUEST( msg->first_line.u.request.method_value ); |
|
613 |
- /* exit succcesfully */ |
|
614 |
- goto end; |
|
615 |
- } |
|
616 |
-#ifdef USE_DNS_FAILOVER |
|
617 |
- }while(dst && cfg_get(core, core_cfg, use_dns_failover) && |
|
618 |
- dns_srv_handle_next(&dns_srv_h, err) && |
|
619 |
- ((err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port, |
|
620 |
- &proto, dns_flags))==0)); |
|
621 |
- if ((err!=0) && (err!=-E_DNS_EOR)){ |
|
622 |
- LM_ERR("resolving %.*s host name in uri failed: %s [%d] (dropping packet)\n", |
|
623 |
- dst->len, ZSW(dst->s), |
|
624 |
- dns_strerror(err), err); |
|
625 |
- ret=ser_error=E_BAD_ADDRESS; |
|
626 |
- goto error; |
|
627 |
- } |
|
628 |
-#endif |
|
629 |
- |
|
630 |
-error: |
|
631 |
- STATS_TX_DROPS; |
|
632 |
-end: |
|
633 |
-#ifdef USE_DNS_FAILOVER |
|
634 |
- if (dst && cfg_get(core, core_cfg, use_dns_failover)){ |
|
635 |
- dns_srv_handle_put(&dns_srv_h); |
|
636 |
- } |
|
637 |
-#endif |
|
638 |
- if (buf) pkg_free(buf); |
|
639 |
- /* received_buf & line_buf will be freed in receive_msg by free_lump_list*/ |
|
640 |
-#if defined STATS_REQ_FWD_OK || defined STATS_REQ_FWD_DROP |
|
641 |
- if(ret==0) |
|
642 |
- STATS_REQ_FWD_OK(); |
|
643 |
- else |
|
644 |
- STATS_REQ_FWD_DROP(); |
|
645 |
-#endif /* STATS_REQ_FWD_* */ |
|
646 |
- return ret; |
|
647 |
-} |
|
648 |
- |
|
649 |
- |
|
650 |
- |
|
651 |
-int update_sock_struct_from_via( union sockaddr_union* to, |
|
652 |
- struct sip_msg* msg, |
|
653 |
- struct via_body* via ) |
|
654 |
-{ |
|
655 |
- struct hostent* he; |
|
656 |
- str* name; |
|
657 |
- int err; |
|
658 |
- unsigned short port; |
|
659 |
- char proto; |
|
660 |
- |
|
661 |
- port=0; |
|
662 |
- if(via==msg->via1){ |
|
663 |
- /* _local_ reply, we ignore any rport or received value |
|
664 |
- * (but we will send back to the original port if rport is |
|
665 |
- * present) */ |
|
666 |
- if ((msg->msg_flags&FL_FORCE_RPORT)||(via->rport)) |
|
667 |
- port=msg->rcv.src_port; |
|
668 |
- else port=via->port; |
|
669 |
- name=&(via->host); /* received=ip in 1st via is ignored (it's |
|
670 |
- not added by us so it's bad) */ |
|
671 |
- }else{ |
|
672 |
- /* "normal" reply, we use rport's & received value if present */ |
|
673 |
- if (via->rport && via->rport->value.s){ |
|
674 |
- LM_DBG("using 'rport'\n"); |
|
675 |
- port=str2s(via->rport->value.s, via->rport->value.len, &err); |
|
676 |
- if (err){ |
|
677 |
- LM_ERR("bad rport value(%.*s)\n", |
|
678 |
- via->rport->value.len, via->rport->value.s); |
|
679 |
- port=0; |
|
680 |
- } |
|
681 |
- } |
|
682 |
- if (via->received){ |
|
683 |
- LM_DBG("using 'received'\n"); |
|
684 |
- name=&(via->received->value); |
|
685 |
- /* making sure that we won't do SRV lookup on "received" |
|
686 |
- * (possible if no DNS_IP_HACK is used)*/ |
|
687 |
- if (port==0) port=via->port?via->port:SIP_PORT; |
|
688 |
- }else{ |
|
689 |
- LM_DBG("using via host\n"); |
|
690 |
- name=&(via->host); |
|
691 |
- if (port==0) port=via->port; |
|
692 |
- } |
|
693 |
- } |
|
694 |
- /* we do now a malloc/memcpy because gethostbyname loves \0-terminated |
|
695 |
- strings; -jiri |
|
696 |
- but only if host is not null terminated |
|
697 |
- (host.s[len] will always be ok for a via) |
|
698 |
- BTW: when is via->host.s non null terminated? tm copy? - andrei |
|
699 |
- Yes -- it happened on generating a 408 by TM; -jiri |
|
700 |
- sip_resolvehost now accepts str -janakj |
|
701 |
- */ |
|
702 |
- LM_DBG("trying SRV lookup\n"); |
|
703 |
- proto=via->proto; |
|
704 |
- he=sip_resolvehost(name, &port, &proto); |
|
705 |
- |
|
706 |
- if (he==0){ |
|
707 |
- LM_NOTICE("resolve_host(%.*s) failure\n", name->len, name->s); |
|
708 |
- return -1; |
|
709 |
- } |
|
710 |
- |
|
711 |
- hostent2su(to, he, 0, port); |
|
712 |
- return 1; |
|
713 |
-} |
|
714 |
- |
|
715 |
- |
|
716 |
- |
|
717 |
-/** removes first via & sends msg to the second |
|
718 |
- * - mode param controls if modules sip response callbacks are executed */ |
|
719 |
-static int do_forward_reply(struct sip_msg* msg, int mode) |
|
720 |
-{ |
|
721 |
- char* new_buf; |
|
722 |
- struct dest_info dst; |
|
723 |
- unsigned int new_len; |
|
724 |
- int r; |
|
725 |
- struct ip_addr ip; |
|
726 |
-#ifdef USE_TCP |
|
727 |
- char* s; |
|
728 |
- int len; |
|
729 |
-#endif |
|
730 |
- init_dest_info(&dst); |
|
731 |
- new_buf=0; |
|
732 |
- /*check if first via host = us */ |
|
733 |
- if (check_via){ |
|
734 |
- if (check_self(&msg->via1->host, |
|
735 |
- msg->via1->port?msg->via1->port:SIP_PORT, |
|
736 |
- msg->via1->proto)!=1){ |
|
737 |
- LM_ERR("host in first via!=me : %.*s:%d\n", |
|
738 |
- msg->via1->host.len, msg->via1->host.s, msg->via1->port); |
|
739 |
- /* send error msg back? */ |
|
740 |
- goto error; |
|
741 |
- } |
|
742 |
- } |
|
743 |
- |
|
744 |
- /* check modules response_f functions */ |
|
745 |
- if(likely(mode==0)) { |
|
746 |
- for (r=0; r<mod_response_cbk_no; r++) |
|
747 |
- if (mod_response_cbks[r](msg)==0) goto skip; |
|
748 |
- } |
|
749 |
- /* we have to forward the reply stateless, so we need second via -bogdan*/ |
|
750 |
- if (parse_headers( msg, HDR_VIA2_F, 0 )==-1 |
|
751 |
- || (msg->via2==0) || (msg->via2->error!=PARSE_OK)) |
|
752 |
- { |
|
753 |
- /* no second via => error */ |
|
754 |
- LM_DBG("reply cannot be forwarded - no 2nd via\n"); |
|
755 |
- goto error; |
|
756 |
- } |
|
757 |
- |
|
758 |
- new_buf = build_res_buf_from_sip_res( msg, &new_len); |
|
759 |
- if (!new_buf){ |
|
760 |
- LM_ERR("building failed\n"); |
|
761 |
- goto error; |
|
762 |
- } |
|
763 |
- |
|
764 |
- dst.proto=msg->via2->proto; |
|
765 |
- SND_FLAGS_OR(&dst.send_flags, &msg->fwd_send_flags, &msg->rpl_send_flags); |
|
766 |
- if (update_sock_struct_from_via( &dst.to, msg, msg->via2 )==-1) goto error; |
|
767 |
-#ifdef USE_COMP |
|
768 |
- dst.comp=msg->via2->comp_no; |
|
769 |
-#endif |
|
770 |
- |
|
771 |
-#if defined USE_TCP || defined USE_SCTP |
|
772 |
- if ( |
|
773 |
-#ifdef USE_TCP |
|
774 |
- dst.proto==PROTO_TCP |
|
775 |
- || dst.proto==PROTO_WS |
|
776 |
-#ifdef USE_TLS |
|
777 |
- || dst.proto==PROTO_TLS |
|
778 |
- || dst.proto==PROTO_WSS |
|
779 |
-#endif |
|
780 |
-#ifdef USE_SCTP |
|
781 |
- || |
|
782 |
-#endif /* USE_SCTP */ |
|
783 |
-#endif /* USE_TCP */ |
|
784 |
-#ifdef USE_SCTP |
|
785 |
- dst.proto==PROTO_SCTP |
|
786 |
-#endif /* USE_SCTP */ |
|
787 |
- ){ |
|
788 |
- /* find id in i param if it exists */ |
|
789 |
- if (msg->via1->i && msg->via1->i->value.s){ |
|
790 |
- s=msg->via1->i->value.s; |
|
791 |
- len=msg->via1->i->value.len; |
|
792 |
- LM_DBG("i=%.*s\n",len, ZSW(s)); |
|
793 |
- if (reverse_hex2int(s, len, (unsigned int*)&dst.id)<0){ |
|
794 |
- LM_ERR("bad via i param \"%.*s\"\n", len, ZSW(s)); |
|
795 |
- dst.id=0; |
|
796 |
- } |
|
797 |
- } |
|
798 |
- |
|
799 |
- } |
|
800 |
-#endif |
|
801 |
- |
|
802 |
- apply_force_send_socket(&dst, msg); |
|
803 |
- |
|
804 |
- /* call onsend_route */ |
|
805 |
- if(dst.send_sock == NULL) { |
|
806 |
- dst.send_sock=get_send_socket(msg, &dst.to, dst.proto); |
|
807 |
- if (dst.send_sock==0){ |
|
808 |
- LM_ERR("cannot forward reply\n"); |
|
809 |
- goto done; |
|
810 |
- } |
|
811 |
- } |
|
812 |
- if (onsend_route_enabled(SIP_REPLY)){ |
|
813 |
- if (run_onsend(msg, &dst, new_buf, new_len)==0){ |
|
814 |
- su2ip_addr(&ip, &(dst.to)); |
|
815 |
- LOG(L_ERR, "forward_reply: reply to %s:%d(%d) dropped" |
|
816 |
- " (onsend_route)\n", ip_addr2a(&ip), |
|
817 |
- su_getport(&(dst.to)), dst.proto); |
|
818 |
- goto error; /* error ? */ |
|
819 |
- } |
|
820 |
- } |
|
821 |
- |
|
822 |
- if (msg_send(&dst, new_buf, new_len)<0) |
|
823 |
- { |
|
824 |
- STATS_RPL_FWD_DROP(); |
|
825 |
- goto error; |
|
826 |
- } |
|
827 |
- |
|
828 |
- done: |
|
829 |
-#ifdef STATS |
|
830 |
- STATS_TX_RESPONSE( (msg->first_line.u.reply.statuscode/100) ); |
|
831 |
-#endif |
|
832 |
- |
|
833 |
- LM_DBG("reply forwarded to %.*s:%d\n", |
|
834 |
- msg->via2->host.len, msg->via2->host.s, |
|
835 |
- (unsigned short) msg->via2->port); |
|
836 |
- |
|
837 |
- STATS_RPL_FWD_OK(); |
|
838 |
- pkg_free(new_buf); |
|
839 |
-skip: |
|
840 |
- return 0; |
|
841 |
-error: |
|
842 |
- if (new_buf) pkg_free(new_buf); |
|
843 |
- return -1; |
|
844 |
-} |
|
845 |
- |
|
846 |
-/** removes first via & sends msg to the second */ |
|
847 |
-int forward_reply(struct sip_msg* msg) |
|
848 |
-{ |
|
849 |
- return do_forward_reply(msg, 0); |
|
850 |
-} |
|
851 |
- |
|
852 |
-/** removes first via & sends msg to the second - no module callbacks */ |
|
853 |
-int forward_reply_nocb(struct sip_msg* msg) |
|
854 |
-{ |
|
855 |
- return do_forward_reply(msg, 1); |
|
856 |
-} |
|
857 |
- |
|
858 |
-static void apply_force_send_socket(struct dest_info* dst, struct sip_msg* msg) |
|
859 |
-{ |
|
860 |
- if (msg->force_send_socket != 0) { |
|
861 |
- dst->send_sock = get_send_socket(msg, &dst->to, dst->proto); |
|
862 |
- } |
|
863 |
-} |
... | ... |
@@ -171,7 +171,7 @@ retry: |
171 | 171 |
su2ip_addr(&ip, &from); |
172 | 172 |
si=find_si(&ip, 0, proto); |
173 | 173 |
if (si==0) goto error; |
174 |
- DBG("DEBUG: get_out_socket: socket determined: %p\n", si ); |
|
174 |
+ LM_DBG("socket determined: %p\n", si ); |
|
175 | 175 |
if (unlikely(mhomed_sock_cache_disabled)){ |
176 | 176 |
close(*temp_sock); |
177 | 177 |
*temp_sock=-1; |
... | ... |
@@ -234,7 +234,7 @@ struct socket_info* get_send_socket2(struct socket_info* force_send_socket, |
234 | 234 |
if (likely(mismatch)) *mismatch=SS_MISMATCH_PROTO; |
235 | 235 |
} |
236 | 236 |
if (unlikely(force_send_socket->address.af!=to->s.sa_family)){ |
237 |
- DBG("get_send_socket: force_send_socket of different af" |
|
237 |
+ LM_DBG("force_send_socket of different af" |
|
238 | 238 |
" (dst %d - %s:%s forced %d -%s:%s:%d)\n", |
239 | 239 |
to->s.sa_family, proto2a(proto), su2a(to, sizeof(*to)), |
240 | 240 |
force_send_socket->address.af, |
... | ... |
@@ -409,7 +409,7 @@ int check_self(str* host, unsigned short port, unsigned short proto) |
409 | 409 |
if (grep_sock_info(host, port, proto)) goto found; |
410 | 410 |
/* try to look into the aliases*/ |
411 | 411 |
if (grep_aliases(host->s, host->len, port, proto)==0){ |
412 |
- DBG("check_self: host != me\n"); |
|
412 |
+ LM_DBG("host != me\n"); |
|
413 | 413 |
return (_check_self_func_list==NULL)?0:run_check_self_func(host, |
414 | 414 |
port, proto); |
415 | 415 |
} |
... | ... |
@@ -553,8 +553,8 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port, |
553 | 553 |
} |
554 | 554 |
#endif |
555 | 555 |
/* send it! */ |
556 |
- DBG("Sending:\n%.*s.\n", (int)len, buf); |
|
557 |
- DBG("orig. len=%d, new_len=%d, proto=%d\n", |
|
556 |
+ LM_DBG("Sending:\n%.*s.\n", (int)len, buf); |
|
557 |
+ LM_DBG("orig. len=%d, new_len=%d, proto=%d\n", |
|
558 | 558 |
msg->len, len, send_info->proto ); |
559 | 559 |
|
560 | 560 |
if (run_onsend(msg, send_info, buf, len)==0){ |
... | ... |
@@ -671,7 +671,7 @@ int update_sock_struct_from_via( union sockaddr_union* to, |
671 | 671 |