- changed sip_msg (new rcv member containing all the ips, ports, protocol)
[sip-router] / forward.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 Fhg Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28
29
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netdb.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38
39 #include "forward.h"
40 #include "hash_func.h"
41 #include "config.h"
42 #include "parser/msg_parser.h"
43 #include "route.h"
44 #include "dprint.h"
45 #include "udp_server.h"
46 #include "globals.h"
47 #include "data_lump.h"
48 #include "ut.h"
49 #include "mem/mem.h"
50 #include "msg_translator.h"
51 #include "sr_module.h"
52 #include "stats.h"
53 #include "ip_addr.h"
54 #include "resolve.h"
55 #include "name_alias.h"
56 #ifdef USE_TCP
57 #include "tcp_server.h"
58 #endif
59
60 #ifdef DEBUG_DMALLOC
61 #include <dmalloc.h>
62 #endif
63
64
65
66 /* returns a socket_info pointer to the sending socket or 0 on error
67  * params: destination socket_union pointer
68  */
69 struct socket_info* get_send_socket(union sockaddr_union* to, int proto)
70 {
71         struct socket_info* send_sock;
72         
73         send_sock=0;
74         /* check if we need to change the socket (different address families -
75          * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
76 #ifdef USE_TCP
77         if (proto==PROTO_TCP){
78                 /* on tcp just use the "main address", we don't really now the
79                  * sending address (we can find it out, but we'll find also to see
80                  * if we listen on it, and if yes on which port -> too complicated*/
81                 switch(to->s.sa_family){
82                         case AF_INET:   send_sock=sendipv4_tcp;
83                                                         break;
84 #ifdef USE_IPV6
85                         case AF_INET6:  send_sock=sendipv6_tcp;
86                                                         break;
87 #endif
88                         default:                LOG(L_ERR, "get_send_socket: BUG: don't know how"
89                                                                         " to forward to af %d\n", to->s.sa_family);
90                 }
91         }else
92 #endif
93               if ((bind_address==0) ||(to->s.sa_family!=bind_address->address.af)){
94                 switch(to->s.sa_family){
95                         case AF_INET:   send_sock=sendipv4;
96                                                         break;
97 #ifdef USE_IPV6
98                         case AF_INET6:  send_sock=sendipv6;
99                                                         break;
100 #endif
101                         default:                LOG(L_ERR, "get_send_socket: BUG: don't know how"
102                                                                         " to forward to af %d\n", to->s.sa_family);
103                 }
104         }else send_sock=bind_address;
105         return send_sock;
106 }
107
108
109
110 /* checks if the host:port is one of the address we listen on;
111  * if port==0, the  port number is ignored
112  * returns 1 if true, 0 if false, -1 on error
113 */
114 int check_self(str* host, unsigned short port)
115 {
116         int r;
117         
118         for (r=0; r<sock_no; r++){
119                 DBG("check_self - checking if host==us: %d==%d && "
120                                 " [%.*s] == [%.*s]\n", 
121                                         host->len,
122                                         sock_info[r].name.len,
123                                         host->len, host->s,
124                                         sock_info[r].name.len, sock_info[r].name.s
125                         );
126                 if  ((port)&&(sock_info[r].port_no!=port)) continue;
127                 if ( (host->len==sock_info[r].name.len) && 
128         #ifdef USE_IPV6
129                         (strncasecmp(host->s, sock_info[r].name.s,
130                                                                  sock_info[r].name.len)==0) /*slower*/
131         #else
132                         (memcmp(host->s, sock_info[r].name.s, 
133                                                                 sock_info[r].name.len)==0)
134         #endif
135                         )
136                         break;
137         /* check if host == ip address */
138                 if (    (!sock_info[r].is_ip) &&
139                                 (host->len==sock_info[r].address_str.len) && 
140         #ifdef USE_IPV6
141                         (strncasecmp(host->s, sock_info[r].address_str.s,
142                                                                  sock_info[r].address_str.len)==0) /*slower*/
143         #else
144                         (memcmp(host->s, sock_info[r].address_str.s, 
145                                                                 sock_info[r].address_str.len)==0)
146         #endif
147                         )
148                         break;
149         }
150         if (r==sock_no){
151                 /* try to look into the aliases*/
152                 if (grep_aliases(host->s, host->len, port)==0){
153                         DBG("check_self: host != me\n");
154                         return 0;
155                 }
156         }
157         return 1;
158 }
159
160
161
162 int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
163 {
164         unsigned int len;
165         char* buf;
166         union sockaddr_union* to;
167         struct socket_info* send_sock;
168         char md5[MD5_LEN];
169         int id; /* used as branch for tcp! */
170         
171         to=0;
172         buf=0;
173         id=0;
174         
175         to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union));
176         if (to==0){
177                 ser_error=E_OUT_OF_MEM;
178                 LOG(L_ERR, "ERROR: forward_request: out of memory\n");
179                 goto error;
180         }
181         
182         
183         /* if error try next ip address if possible */
184         if (p->ok==0){
185                 if (p->host.h_addr_list[p->addr_idx+1])
186                         p->addr_idx++;
187                 else p->addr_idx=0;
188                 p->ok=1;
189         }
190         
191         hostent2su(to, &p->host, p->addr_idx, 
192                                 (p->port)?htons(p->port):htons(SIP_PORT));
193         p->tx++;
194         p->tx_bytes+=len;
195         
196
197         send_sock=get_send_socket(to, proto);
198         if (send_sock==0){
199                 LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d "
200                                 "no coresponding listening socket\n", to->s.sa_family);
201                 ser_error=E_NO_SOCKET;
202                 goto error1;
203         }
204
205         /* calculate branch for outbound request;  if syn_branch is turned off,
206            calculate is from transaction key, i.e., as an md5 of From/To/CallID/
207            CSeq exactly the same way as TM does; good for reboot -- than messages
208            belonging to transaction lost due to reboot will still be forwarded
209            with the same branch parameter and will be match-able downstream
210
211        if it is turned on, we don't care about reboot; we simply put a simple
212            value in there; better for performance
213         */
214
215 #ifdef USE_TCP
216         if (msg->rcv.proto==PROTO_TCP) id=msg->rcv.proto_reserved1;
217 #endif
218         if (syn_branch ) {
219                 *msg->add_to_branch_s='0';
220                 msg->add_to_branch_len=1;
221         } else {
222                 if (!char_msg_val( msg, md5 ))  { /* parses transaction key */
223                         LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
224                         goto error1;
225                 }
226                 msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
227                 if (!branch_builder( msg->hash_index, 0, md5, id /* 0-th branch */,
228                                         msg->add_to_branch_s, &msg->add_to_branch_len )) {
229                         LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
230                         goto error1;
231                 }
232         }
233
234         buf = build_req_buf_from_sip_req( msg, &len, send_sock,  proto);
235         if (!buf){
236                 LOG(L_ERR, "ERROR: forward_request: building failed\n");
237                 goto error1;
238         }
239          /* send it! */
240         DBG("Sending:\n%s.\n", buf);
241         DBG("orig. len=%d, new_len=%d, proto=%d\n", msg->len, len, proto );
242         
243         
244         if (proto==PROTO_UDP){
245                 if (udp_send(send_sock, buf, len,  to)==-1){
246                                 ser_error=E_SEND;
247                                 p->errors++;
248                                 p->ok=0;
249                                 STATS_TX_DROPS;
250                                 goto error1;
251                 }
252         }
253 #ifdef USE_TCP
254          else if (proto==PROTO_TCP){
255                 if (tcp_send(buf, len, to, 0)==-1){
256                                 ser_error=E_SEND;
257                                 p->errors++;
258                                 p->ok=0;
259                                 STATS_TX_DROPS;
260                                 goto error1;
261                 }
262         }
263 #endif
264          else{
265                 LOG(L_CRIT, "BUG: forward_request: unknown proto %d\n", proto);
266                 ser_error=E_SEND;
267                 STATS_TX_DROPS;
268                 goto error1;
269         }
270
271         /* sent requests stats */
272         STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
273         
274         pkg_free(buf);
275         free(to);
276         /* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
277         return 0;
278
279 error1:
280         free(to);
281 error:
282         if (buf) pkg_free(buf);
283         return -1;
284 }
285
286
287
288 int update_sock_struct_from_via( union sockaddr_union* to,
289                                                                  struct via_body* via )
290 {
291         struct hostent* he;
292         char *host_copy;
293         str* name;
294         unsigned short port;
295
296
297         if (via->received){
298                 DBG("update_sock_struct_from_via: using 'received'\n");
299                 name=&(via->received->value);
300                 /* making sure that we won't do SRV lookup on "received"
301                  * (possible if no DNS_IP_HACK is used)*/
302                 port=via->port?via->port:SIP_PORT; 
303         }else{
304                 DBG("update_sock_struct_from_via: using via host\n");
305                 name=&(via->host);
306                 port=via->port;
307         }
308         /* we do now a malloc/memcpy because gethostbyname loves \0-terminated 
309            strings; -jiri 
310            but only if host is not null terminated
311            (host.s[len] will always be ok for a via)
312             BTW: when is via->host.s non null terminated? tm copy? - andrei 
313             Yes -- it happened on generating a 408 by TM; -jiri
314         */
315         if (name->s[name->len]){
316                 host_copy=pkg_malloc( name->len+1 );
317                 if (!host_copy) {
318                         LOG(L_NOTICE, "ERROR: update_sock_struct_from_via:"
319                                                         " not enough memory\n");
320                         return -1;
321                 }
322                 memcpy(host_copy, name->s, name->len );
323                 host_copy[name->len]=0;
324                 DBG("update_sock_struct_from_via: trying SRV lookup\n");
325                 he=sip_resolvehost(host_copy, &port);
326                 
327                 pkg_free( host_copy );
328         }else{
329                 DBG("update_sock_struct_from_via: trying SRV lookup\n");
330                 he=sip_resolvehost(name->s, &port);
331         }
332         
333         if (he==0){
334                 LOG(L_NOTICE, "ERROR:forward_reply:resolve_host(%s) failure\n",
335                                 name->s);
336                 return -1;
337         }
338         hostent2su(to, he, 0, htons(port));
339         return 1;
340 }
341
342
343 /* removes first via & sends msg to the second */
344 int forward_reply(struct sip_msg* msg)
345 {
346         char* new_buf;
347         union sockaddr_union* to;
348         struct socket_info* send_sock;
349         unsigned int new_len;
350         struct sr_module *mod;
351         int proto;
352 #ifdef USE_TCP
353         char* s;
354         char* p;
355         int len;
356         int id;
357 #endif
358         
359         to=0;
360         new_buf=0;
361         /*check if first via host = us */
362         if (check_via){
363                 if (check_self(&msg->via1->host,
364                                         msg->via1->port?msg->via1->port:SIP_PORT)!=1){
365                         LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
366                                         " %.*s:%d\n", msg->via1->host.len, msg->via1->host.s,
367                                                                         msg->via1->port);
368                         /* send error msg back? */
369                         goto error;
370                 }
371         }
372         /* quick hack, slower for mutliple modules*/
373         for (mod=modules;mod;mod=mod->next){
374                 if ((mod->exports) && (mod->exports->response_f)){
375                         DBG("forward_reply: found module %s, passing reply to it\n",
376                                         mod->exports->name);
377                         if (mod->exports->response_f(msg)==0) goto skip;
378                 }
379         }
380
381         /* we have to forward the reply stateless, so we need second via -bogdan*/
382         if (parse_headers( msg, HDR_VIA2, 0 )==-1 
383                 || (msg->via2==0) || (msg->via2->error!=PARSE_OK))
384         {
385                 /* no second via => error */
386                 LOG(L_ERR, "ERROR: forward_msg: no 2nd via found in reply\n");
387                 goto error;
388         }
389
390         to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union));
391         if (to==0){
392                 LOG(L_ERR, "ERROR: forward_reply: out of memory\n");
393                 goto error;
394         }
395
396         new_buf = build_res_buf_from_sip_res( msg, &new_len);
397         if (!new_buf){
398                 LOG(L_ERR, "ERROR: forward_reply: building failed\n");
399                 goto error;
400         }
401
402         if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
403         send_sock=get_send_socket(to, msg->rcv.proto);
404         if (send_sock==0){
405                 LOG(L_ERR, "forward_reply: ERROR: no sending socket found\n");
406                 goto error;
407         }
408
409         proto=msg->via2->proto;
410         if (proto==PROTO_UDP){
411                 if (udp_send(send_sock, new_buf,new_len,  to)==-1)
412                 {
413                         STATS_TX_DROPS;
414                         goto error;
415                 }
416         }
417 #ifdef USE_TCP
418          else if (proto==PROTO_TCP){
419                  id=0;
420                 /* find id in branch if it exists */
421                 if ((msg->via1->branch)&&(msg->via1->branch->value.len>MCOOKIE_LEN) &&
422                         (memcmp(msg->via1->branch->value.s, MCOOKIE, MCOOKIE_LEN)==0)){
423                         DBG("forward_reply: found branch\n");
424                         s=msg->via1->branch->value.s+MCOOKIE_LEN;
425                         len=msg->via1->branch->value.len-MCOOKIE_LEN;
426                         for (p=s; p<s+len  && *p!=BRANCH_SEPARATOR; p++);
427                         p++;
428                         for(;p<s+len && *p!=BRANCH_SEPARATOR; p++);
429                         p++;
430                         if (p<s+len){
431                                 /* we found the second BRANCH_SEPARATOR, p points after it */
432                                 len-=(int)(p-s);
433                                 id=reverse_hex2int(p, len);
434                                 DBG("forward_reply: id= %x\n", id);
435                         }else{
436                                 DBG("forward_reply: no id in branch\n");
437                         }
438                 }               
439                                 
440                 if (tcp_send(new_buf, new_len,  to, id)==-1)
441                 {
442                         STATS_TX_DROPS;
443                         goto error;
444                 }
445         } 
446 #endif
447         else{
448                 LOG(L_CRIT, "BUG: forward_reply: unknown proto %d\n", proto);
449                 goto error;
450         }
451 #ifdef STATS
452                 STATS_TX_RESPONSE(  (msg->first_line.u.reply.statuscode/100) );
453 #endif
454
455         DBG(" reply forwarded to %s:%d\n", msg->via2->host.s,
456                 (unsigned short) msg->via2->port);
457
458         pkg_free(new_buf);
459         free(to);
460 skip:
461         return 0;
462 error:
463         if (new_buf) pkg_free(new_buf);
464         if (to) free(to);
465         return -1;
466 }