4 * Copyright (C) 2001-2003 FhG Fokus
6 * This file is part of ser, a free SIP server.
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
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:
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.
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
29 * 2001-??-?? created by andrei
30 * ????-??-?? lots of changes by a lot of people
31 * 2003-01-23 support for determination of outbound interface added :
32 * get_out_socket (jiri)
33 * 2003-01-24 reply to rport support added, contributed by
34 * Maxim Sobolev <sobomax@FreeBSD.org> and modified by andrei
35 * 2003-02-11 removed calls to upd_send & tcp_send & replaced them with
36 * calls to msg_send (andrei)
37 * 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
38 * 2003-04-02 fixed get_send_socket for tcp fwd to udp (andrei)
39 * 2003-04-03 added su_setport (andrei)
40 * 2003-04-04 update_sock_struct_from_via now differentiates between
41 * local replies & "normal" replies (andrei)
42 * 2003-04-12 update_sock_struct_from via uses also FL_FORCE_RPORT for
43 * local replies (andrei)
44 * 2003-08-21 check_self properly handles ipv6 addresses & refs (andrei)
45 * 2003-10-21 check_self updated to handle proto (andrei)
46 * 2003-10-24 converted to the new socket_info lists (andrei)
54 #include <sys/types.h>
55 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
61 #include "hash_func.h"
63 #include "parser/msg_parser.h"
67 #include "data_lump.h"
70 #include "msg_translator.h"
71 #include "sr_module.h"
74 #include "name_alias.h"
75 #include "socket_info.h"
81 /* return a socket_info_pointer to the sending socket; as opposed to
82 * get_send_socket, which returns process's default socket, get_out_socket
83 * attempts to determine the outbound interface which will be used;
84 * it creates a temporary connected socket to determine it; it will
85 * be very likely noticeably slower, but it can deal better with
88 struct socket_info* get_out_socket(union sockaddr_union* to, int proto)
92 union sockaddr_union from;
93 struct socket_info* si;
95 if (proto!=PROTO_UDP) {
96 LOG(L_CRIT, "BUG: get_out_socket can only be called for UDP\n");
100 temp_sock=socket(to->s.sa_family, SOCK_DGRAM, 0 );
102 LOG(L_ERR, "ERROR: get_out_socket: socket() failed: %s\n",
106 if (connect(temp_sock, &to->s, sockaddru_len(*to))==-1) {
107 LOG(L_ERR, "ERROR: get_out_socket: connect failed: %s\n",
112 if (getsockname(temp_sock, &from.s, &len)==-1) {
113 LOG(L_ERR, "ERROR: get_out_socket: getsockname failed: %s\n",
117 for (si=udp_listen; si; si=si->next) {
118 switch(from.s.sa_family) {
120 if (si->address.af!=AF_INET)
122 if (memcmp(&si->address.u,
125 goto found; /* success */
127 #if defined(USE_IPV6)
129 if (si->address.af!=AF_INET6)
131 if (memcmp(&si->address.u,
132 &from.sin6.sin6_addr, len)==0)
136 default: LOG(L_ERR, "ERROR: get_out_socket: "
137 "unknown family: %d\n",
143 LOG(L_ERR, "ERROR: get_out_socket: no socket found\n");
148 DBG("DEBUG: get_out_socket: socket determined: %p\n", si );
154 /* returns a socket_info pointer to the sending socket or 0 on error
155 * params: destination socket_union pointer
157 struct socket_info* get_send_socket(union sockaddr_union* to, int proto)
159 struct socket_info* send_sock;
161 if (mhomed && proto==PROTO_UDP) return get_out_socket(to, proto);
164 /* check if we need to change the socket (different address families -
165 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
169 /* on tcp just use the "main address", we don't really now the
170 * sending address (we can find it out, but we'll need also to see
171 * if we listen on it, and if yes on which port -> too complicated*/
172 switch(to->s.sa_family){
174 case AF_INET: send_sock=sendipv4_tcp;
177 case AF_INET6: send_sock=sendipv6_tcp;
180 default: LOG(L_ERR, "get_send_socket: BUG: don't know how"
181 " to forward to af %d\n", to->s.sa_family);
187 switch(to->s.sa_family){
189 case AF_INET: send_sock=sendipv4_tls;
192 case AF_INET6: send_sock=sendipv6_tls;
195 default: LOG(L_ERR, "get_send_socket: BUG: don't know how"
196 " to forward to af %d\n", to->s.sa_family);
201 if ((bind_address==0)||(to->s.sa_family!=bind_address->address.af)||
202 (bind_address->proto!=PROTO_UDP)){
203 switch(to->s.sa_family){
204 case AF_INET: send_sock=sendipv4;
207 case AF_INET6: send_sock=sendipv6;
210 default: LOG(L_ERR, "get_send_socket: BUG: don't know"
211 " how to forward to af %d\n",
214 }else send_sock=bind_address;
217 LOG(L_CRIT, "BUG: get_send_socket: unknown proto %d\n", proto);
224 /* checks if the proto: host:port is one of the address we listen on;
225 * if port==0, the port number is ignored
226 * if proto==0 (PROTO_NONE) the protocol is ignored
227 * returns 1 if true, 0 if false, -1 on error
228 * WARNING: uses str2ip6 so it will overwrite any previous
229 * unsaved result of this function (static buffer)
231 int check_self(str* host, unsigned short port, unsigned short proto)
235 struct socket_info* si;
236 unsigned short c_proto;
244 if ((h_len>2)&&((*hname)=='[')&&(hname[h_len-1]==']')){
245 /* ipv6 reference, skip [] */
250 c_proto=proto?proto:PROTO_UDP;
252 /* get the proper sock list */
254 case PROTO_NONE: /* we'll use udp and not all the lists FIXME: */
270 LOG(L_WARN, "WARNING: check_self: "
271 "unknown proto %d\n", c_proto);
272 return 0; /* false */
274 for (; si; si=si->next){
275 DBG("check_self - checking if host==us: %d==%d && "
276 " [%.*s] == [%.*s]\n",
280 si->name.len, si->name.s
283 DBG("check_self - checking if port %d matches port %d\n",
285 if (si->port_no!=port) {
289 if ( (h_len==si->name.len) &&
290 (strncasecmp(hname, si->name.s,
291 si->name.len)==0) /*slower*/)
292 /* comp. must be case insensitive, host names
293 * can be written in mixed case, it will also match
294 * ipv6 addresses if we are lucky*/
296 /* check if host == ip address */
298 /* ipv6 case is uglier, host can be [3ffe::1] */
301 if (ip_addr_cmp(ip6, &si->address))
302 goto found; /* match */
304 continue; /* no match, but this is an ipv6 address
305 so no point in trying ipv4 */
309 if ( (!(si->flags&SI_IS_IP)) &&
310 (h_len==si->address_str.len) &&
311 (memcmp(hname, si->address_str.s,
312 si->address_str.len)==0)
316 }while( (proto==0) && (c_proto=next_proto(c_proto)) );
318 /* try to look into the aliases*/
319 if (grep_aliases(hname, h_len, port, proto)==0){
320 DBG("check_self: host != me\n");
329 int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
333 union sockaddr_union* to;
334 struct socket_info* send_sock;
336 int id; /* used as branch for tcp! */
342 to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
344 ser_error=E_OUT_OF_MEM;
345 LOG(L_ERR, "ERROR: forward_request: out of memory\n");
350 /* if error try next ip address if possible */
352 if (p->host.h_addr_list[p->addr_idx+1])
358 hostent2su(to, &p->host, p->addr_idx,
359 (p->port)?p->port:SIP_PORT);
364 send_sock=get_send_socket(to, proto);
366 LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
367 "no corresponding listening socket\n", to->s.sa_family, proto);
368 ser_error=E_NO_SOCKET;
372 /* calculate branch for outbound request; if syn_branch is turned off,
373 calculate is from transaction key, i.e., as an md5 of From/To/CallID/
374 CSeq exactly the same way as TM does; good for reboot -- than messages
375 belonging to transaction lost due to reboot will still be forwarded
376 with the same branch parameter and will be match-able downstream
378 if it is turned on, we don't care about reboot; we simply put a simple
379 value in there; better for performance
382 *msg->add_to_branch_s='0';
383 msg->add_to_branch_len=1;
385 if (!char_msg_val( msg, md5 )) { /* parses transaction key */
386 LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
389 msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
390 if (!branch_builder( msg->hash_index, 0, md5, id /* 0-th branch */,
391 msg->add_to_branch_s, &msg->add_to_branch_len )) {
392 LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
397 buf = build_req_buf_from_sip_req( msg, &len, send_sock, proto);
399 LOG(L_ERR, "ERROR: forward_request: building failed\n");
403 DBG("Sending:\n%.*s.\n", (int)len, buf);
404 DBG("orig. len=%d, new_len=%d, proto=%d\n", msg->len, len, proto );
406 if (msg_send(send_sock, proto, to, 0, buf, len)<0){
414 /* sent requests stats */
415 STATS_TX_REQUEST( msg->first_line.u.request.method_value );
419 /* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
425 if (buf) pkg_free(buf);
431 int update_sock_struct_from_via( union sockaddr_union* to,
433 struct via_body* via )
442 /* _local_ reply, we ignore any rport or received value
443 * (but we will send back to the original port if rport is
445 if ((msg->msg_flags&FL_FORCE_RPORT)||(via->rport))
446 port=msg->rcv.src_port;
448 name=&(via->host); /* received=ip in 1st via is ignored (it's
449 not added by us so it's bad) */
451 /* "normal" reply, we use rport's & received value if present */
452 if (via->rport && via->rport->value.s){
453 DBG("update_sock_struct_from_via: using 'rport'\n");
454 port=str2s(via->rport->value.s, via->rport->value.len, &err);
456 LOG(L_NOTICE, "ERROR: forward_reply: bad rport value(%.*s)\n",
457 via->rport->value.len, via->rport->value.s);
462 DBG("update_sock_struct_from_via: using 'received'\n");
463 name=&(via->received->value);
464 /* making sure that we won't do SRV lookup on "received"
465 * (possible if no DNS_IP_HACK is used)*/
466 if (port==0) port=via->port?via->port:SIP_PORT;
468 DBG("update_sock_struct_from_via: using via host\n");
470 if (port==0) port=via->port;
473 /* we do now a malloc/memcpy because gethostbyname loves \0-terminated
475 but only if host is not null terminated
476 (host.s[len] will always be ok for a via)
477 BTW: when is via->host.s non null terminated? tm copy? - andrei
478 Yes -- it happened on generating a 408 by TM; -jiri
479 sip_resolvehost now accepts str -janakj
481 DBG("update_sock_struct_from_via: trying SRV lookup\n");
482 he=sip_resolvehost(name, &port, via->proto);
485 LOG(L_NOTICE, "ERROR:forward_reply:resolve_host(%.*s) failure\n",
490 hostent2su(to, he, 0, port);
496 /* removes first via & sends msg to the second */
497 int forward_reply(struct sip_msg* msg)
500 union sockaddr_union* to;
501 unsigned int new_len;
502 struct sr_module *mod;
504 int id; /* used only by tcp*/
513 /*check if first via host = us */
515 if (check_self(&msg->via1->host,
516 msg->via1->port?msg->via1->port:SIP_PORT,
517 msg->via1->proto)!=1){
518 LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
519 " %.*s:%d\n", msg->via1->host.len, msg->via1->host.s,
521 /* send error msg back? */
525 /* quick hack, slower for multiple modules*/
526 for (mod=modules;mod;mod=mod->next){
527 if ((mod->exports) && (mod->exports->response_f)){
528 DBG("forward_reply: found module %s, passing reply to it\n",
530 if (mod->exports->response_f(msg)==0) goto skip;
534 /* we have to forward the reply stateless, so we need second via -bogdan*/
535 if (parse_headers( msg, HDR_VIA2, 0 )==-1
536 || (msg->via2==0) || (msg->via2->error!=PARSE_OK))
538 /* no second via => error */
539 LOG(L_ERR, "ERROR: forward_reply: no 2nd via found in reply\n");
543 to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
545 LOG(L_ERR, "ERROR: forward_reply: out of memory\n");
549 new_buf = build_res_buf_from_sip_res( msg, &new_len);
551 LOG(L_ERR, "ERROR: forward_reply: building failed\n");
555 proto=msg->via2->proto;
556 if (update_sock_struct_from_via( to, msg, msg->via2 )==-1) goto error;
565 /* find id in i param if it exists */
566 if (msg->via1->i&&msg->via1->i->value.s){
567 s=msg->via1->i->value.s;
568 len=msg->via1->i->value.len;
569 DBG("forward_reply: i=%.*s\n",len, s);
570 id=reverse_hex2int(s, len);
571 DBG("forward_reply: id= %x\n", id);
576 if (msg_send(0, proto, to, id, new_buf, new_len)<0) goto error;
578 STATS_TX_RESPONSE( (msg->first_line.u.reply.statuscode/100) );
581 DBG(" reply forwarded to %.*s:%d\n",
582 msg->via2->host.len, msg->via2->host.s,
583 (unsigned short) msg->via2->port);
590 if (new_buf) pkg_free(new_buf);
591 if (to) pkg_free(to);