First working release
[sip-router] / forward.c
1 /*
2  * $Id$
3  */
4
5
6 #include <string.h>
7 #include <netdb.h>
8 #include <netinet/in.h>
9
10 #include "forward.h"
11 #include "config.h"
12 #include "msg_parser.h"
13 #include "route.h"
14 #include "dprint.h"
15 #include "udp_server.h"
16
17 #define MAX_VIA_LINE_SIZE      240
18 #define MAX_RECEIVED_SIZE  57
19
20
21
22 int forward_request(char * orig, char* buf, 
23                                          unsigned int len,
24                                          struct sip_msg* msg,
25                                          struct route_elem* re)
26 {
27         unsigned int new_len, via_len, received_len;
28         char line_buf[MAX_VIA_LINE_SIZE];
29         char received_buf[MAX_RECEIVED_SIZE];
30         char* new_buf;
31         int offset, s_offset, size;
32         struct sockaddr_in to;
33
34         received_len=0;
35
36         via_len=snprintf(line_buf, MAX_VIA_LINE_SIZE, "Via: SIP/2.0/UDP %s:%d\r\n",
37                                                 our_name, our_port);
38         /* check if received needs to be added */
39         /* if check_address(source_ip, msg->via1.host) */
40         received_len=snprintf(received_buf, MAX_RECEIVED_SIZE, ";received=%s",
41                                                         "10.11.12.13");
42         
43         new_len=len+via_len+received_len;
44         new_buf=(char*)malloc(new_len+1);
45         if (new_buf==0){
46                 DPrint("ERROR: forward_request: out of memory\n");
47                 goto error1;
48         }
49 /* copy msg till first via */
50         offset=s_offset=0;
51         size=msg->via1.hdr-buf;
52         memcpy(new_buf, orig, size);
53         offset+=size;
54         s_offset+=size;
55  /* add our via */
56         memcpy(new_buf+offset, line_buf, via_len);
57         offset+=via_len;
58  /* modify original via if neccesarry (received=...)*/
59         if (received_len){
60                 if (msg->via1.params){
61                                 size= msg->via1.params-msg->via1.hdr-1; /*compensate for ';' */
62                 }else{
63                                 size= msg->via1.host-msg->via1.hdr+strlen(msg->via1.host);
64                                 if (msg->via1.port!=0){
65                                         size+=strlen(msg->via1.hdr+size+1)+1; /* +1 for ':'*/
66                                 }
67                 }
68                 memcpy(new_buf+offset, orig+s_offset, 
69                                                                 size);
70                 offset+=size;
71                 s_offset+=size;
72                 memcpy(new_buf+offset, received_buf, received_len);
73                 offset+=received_len;
74         }
75         /* copy the rest of the msg */
76         memcpy(new_buf+offset, orig+s_offset, len-s_offset);
77         new_buf[new_len]=0;
78
79          /* send it! */
80         printf("Sending:\n%s.\n", new_buf);
81         printf("orig. len=%d, new_len=%d, via_len=%d, received_len=%d\n",
82                         len, new_len, via_len, received_len);
83
84         to.sin_family = AF_INET;
85         to.sin_port = (re->port)?htons(re->port):htons(SIP_PORT);
86         /* if error try next ip address if possible */
87         if (re->ok==0){
88                 if (re->host.h_addr_list[re->current_addr_idx+1])
89                         re->current_addr_idx++;
90                 re->ok=1;
91         }
92         /* ? not 64bit clean?*/
93         to.sin_addr.s_addr=*((long*)re->host.h_addr_list[re->current_addr_idx]);
94
95         re->tx++;
96         re->tx_bytes+=new_len;
97         if (udp_send(new_buf, new_len, &to, sizeof(to))==-1){
98                         re->errors++;
99                         re->ok=0;
100                         goto error;
101         }
102
103         free(new_buf);
104         return 0;
105 error:
106         free(new_buf);
107 error1:
108         return -1;
109
110 }
111
112
113
114 /* removes first via & sends msg to the second */
115 int forward_reply(char * orig, char* buf, 
116                                          unsigned int len,
117                                          struct sip_msg* msg)
118 {
119
120
121         unsigned int new_len, via_len;
122         char* new_buf;
123         int offset, s_offset, size;
124         struct hostent* he;
125         struct sockaddr_in to;
126
127
128         /* we must remove the first via */
129         via_len=msg->via1.size;
130         size=msg->via1.hdr-buf;
131         if (msg->via1.next){
132                 /* keep hdr =substract hdr size +1 (hdr':') and add
133                  */
134                 via_len-=strlen(msg->via1.hdr)+1;
135                 size+=strlen(msg->via1.hdr)+1;
136         }
137         new_len=len-size;
138         new_buf=(char*)malloc(new_len);
139         if (new_buf==0){
140                 DPrint("ERROR: forward_reply: out of memory\n");
141                 goto error;
142         }
143         memcpy(new_buf, orig, size);
144         offset=size;
145         s_offset=size+via_len;
146         memcpy(new_buf+offset,orig+s_offset, len-s_offset);
147          /* send it! */
148         printf("Sending: to %s:%d, \n%s.\n",
149                         msg->via2.host, 
150                         (unsigned short)msg->via2.port,
151                         new_buf);
152         /* fork? gethostbyname will probably block... */
153         he=gethostbyname(msg->via2.host);
154         if (he==0){
155                 DPrint("ERROR:forward_reply:gethostbyname failure\n");
156                 goto error;
157         }
158         to.sin_family = AF_INET;
159         to.sin_port = (msg->via2.port)?htons(msg->via2.port):htons(SIP_PORT);
160         to.sin_addr.s_addr=*((long*)he->h_addr_list[0]);
161         
162         if (udp_send(new_buf,new_len, &to, sizeof(to))==-1)
163                 goto error;
164         
165         free(new_buf);
166         return 0;
167
168 error:
169         if (new_buf) free(new_buf);
170         return -1;
171 }