forward.c
888ca09d
 /*
  * $Id$
  */
 
 
 #include <string.h>
3e429f5c
 #include <stdio.h>
 #include <stdlib.h>
9a3dc64b
 #include <sys/types.h>
 #include <sys/socket.h>
e60a9728
 #include <netdb.h>
 #include <netinet/in.h>
1b1b19d8
 #include <arpa/inet.h>
888ca09d
 
 #include "forward.h"
e60a9728
 #include "config.h"
888ca09d
 #include "msg_parser.h"
 #include "route.h"
 #include "dprint.h"
e60a9728
 #include "udp_server.h"
1b1b19d8
 #include "globals.h"
831faabf
 #include "data_lump.h"
104316b6
 #include "ut.h"
dda9dab1
 #include "mem/mem.h"
c2c6a6bf
 #include "msg_translator.h"
031e278e
 #include "sr_module.h"
dda9dab1
 #include "stats.h"
888ca09d
 
03150098
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
 #endif
 
b2e71d5b
 
1b1b19d8
 
3e429f5c
 int forward_request( struct sip_msg* msg, struct proxy_l * p)
888ca09d
 {
c2c6a6bf
 	unsigned int len;
ac79e819
 	char* buf;
 	struct sockaddr_in* to;
c2c6a6bf
 
ac79e819
 	to=0;
5843cd1b
 	buf = build_req_buf_from_sip_req( msg, &len);
c2c6a6bf
 	if (!buf){
 		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
 		goto error;
 	}
 
dc862225
 	to=(struct sockaddr_in*)malloc(sizeof(struct sockaddr));
 	if (to==0){
68a3fc65
 		LOG(L_ERR, "ERROR: forward_request: out of memory\n");
dc862225
 		goto error;
 	}
888ca09d
 
 	 /* send it! */
ac79e819
 	DBG("Sending:\n%s.\n", buf);
c2c6a6bf
 	DBG("orig. len=%d, new_len=%d\n", msg->len, len );
e60a9728
 
dc862225
 	to->sin_family = AF_INET;
4ac74c03
 	to->sin_port = (p->port)?htons(p->port):htons(SIP_PORT);
e60a9728
 	/* if error try next ip address if possible */
4ac74c03
 	if (p->ok==0){
 		if (p->host.h_addr_list[p->addr_idx+1])
 			p->addr_idx++;
 		p->ok=1;
e60a9728
 	}
 	/* ? not 64bit clean?*/
4ac74c03
 	to->sin_addr.s_addr=*((long*)p->host.h_addr_list[p->addr_idx]);
e60a9728
 
4ac74c03
 	p->tx++;
c2c6a6bf
 	p->tx_bytes+=len;
5b253cc6
 
c2c6a6bf
 	if (udp_send( buf, len, (struct sockaddr*) to,
3e429f5c
 				sizeof(struct sockaddr_in))==-1){
4ac74c03
 			p->errors++;
 			p->ok=0;
dda9dab1
 			STATS_TX_DROPS;
e60a9728
 			goto error;
c2c6a6bf
 	}
f571aa35
 	/* sent requests stats */
dda9dab1
 	else STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
c2c6a6bf
 	free(buf);
dc862225
 	free(to);
831faabf
 	/* received_buf & line_buf will be freed in receiv_msg by free_lump_list*/
888ca09d
 	return 0;
 error:
c2c6a6bf
 	if (buf) free(buf);
dc862225
 	if (to) free(to);
888ca09d
 	return -1;
 }
 
 
68a3fc65
 int update_sock_struct_from_via( struct sockaddr_in* to,  struct via_body* via )
 {
 	int err;
ac79e819
 	struct hostent* he;
68a3fc65
 
 	to->sin_family = AF_INET;
 	to->sin_port = (via->port)?htons(via->port): htons(SIP_PORT);
 
 #ifdef DNS_IP_HACK
 	to->sin_addr.s_addr=str2ip(via->host.s, via->host.len, &err);
 	if (err)
 #endif
 	{
 		/* fork? gethostbyname will probably block... */
 		he=gethostbyname(via->host.s);
 		if (he==0){
 			LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n",
 					via->host.s);
 			return -1;
 		}
 		to->sin_addr.s_addr=*((long*)he->h_addr_list[0]);
 	}
 	return 1;
 }
 
888ca09d
 
 /* removes first via & sends msg to the second */
4ac74c03
 int forward_reply(struct sip_msg* msg)
888ca09d
 {
8cc98445
 	int  r;
ac79e819
 	char* new_buf;
 	struct sockaddr_in* to;
8cc98445
 	unsigned int new_len;
031e278e
 	struct sr_module *mod;
104316b6
 #ifdef DNS_IP_HACK
 	int err;
 #endif
c2c6a6bf
 
888ca09d
 
 
ac79e819
 	to=0;
 	new_buf=0;
1b1b19d8
 	/*check if first via host = us */
 	if (check_via){
 		for (r=0; r<addresses_no; r++)
e72b5b50
 			if(strcmp(msg->via1->host.s, names[r])==0) break;
1b1b19d8
 		if (r==addresses_no){
f8d46776
 			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
e72b5b50
 					" %s\n", msg->via1->host);
1b1b19d8
 			/* send error msg back? */
 			goto error;
 		}
 	}
c2c6a6bf
 
8cc98445
 	/* here will be called the T Module !!!!!!  */
031e278e
 	/* quick hack, slower for mutliple modules*/
 	for (mod=modules;mod;mod=mod->next){
 		if ((mod->exports) && (mod->exports->response_f)){
 			DBG("forward_reply: found module %s, passing reply to it\n",
 					mod->exports->name);
 			if (mod->exports->response_f(msg)==0) goto skip;
 		}
 	}
 	
 	to=(struct sockaddr_in*)malloc(sizeof(struct sockaddr));
 	if (to==0){
 		LOG(L_ERR, "ERROR: forward_reply: out of memory\n");
 		goto error;
 	}
8cc98445
 
5843cd1b
 	new_buf = build_res_buf_from_sip_res( msg, &new_len);
8cc98445
 	if (!new_buf){
 		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
888ca09d
 		goto error;
 	}
8cc98445
 
888ca09d
 	 /* send it! */
68a3fc65
 	/* moved to udp_send; -jiri
 
efeaaf53
 	DBG("Sending: to %s:%d, \n%s.\n",
c2c6a6bf
 			msg->via2->host.s,
e72b5b50
 			(unsigned short)msg->via2->port,
888ca09d
 			new_buf);
68a3fc65
 	*/
104316b6
 
68a3fc65
 	if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
5b253cc6
 
c2c6a6bf
 	if (udp_send(new_buf,new_len, (struct sockaddr*) to,
 					sizeof(struct sockaddr_in))==-1)
f571aa35
 	{
dda9dab1
 		STATS_TX_DROPS;
e60a9728
 		goto error;
f571aa35
 	}
9598488f
 	else {
 #ifdef STATS
 		int j = msg->first_line.u.reply.statuscode/100;
 		STATS_TX_RESPONSE(  j );
 #endif
 	}
e60a9728
 	free(new_buf);
dc862225
 	free(to);
031e278e
 skip:
888ca09d
 	return 0;
 error:
e60a9728
 	if (new_buf) free(new_buf);
dc862225
 	if (to) free(to);
888ca09d
 	return -1;
 }