core: print src address details if initial message parsing fails
[sip-router] / receive.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  * History:
28  * ---------
29  * 2003-02-28 scratchpad compatibility abandoned (jiri)
30  * 2003-01-29 transport-independent message zero-termination in
31  *            receive_msg (jiri)
32  * 2003-02-07 undoed jiri's zero term. changes (they break tcp) (andrei)
33  * 2003-02-10 moved zero-term in the calling functions (udp_receive &
34  *            tcp_read_req)
35  * 2003-08-13 fixed exec_pre_cb returning 0 (backported from stable) (andrei)
36  * 2004-02-06 added user preferences support - destroy_avps() (bogdan)
37  * 2004-04-30 exec_pre_cb is called after basic sanity checks (at least one
38  *            via present & parsed ok)  (andrei)
39  * 2004-08-23 avp core changed - destroy_avp-> reset_avps (bogdan)
40  * 2006-11-29 nonsip_msg hooks called for non-sip msg (e.g HTTP) (andrei)
41  */
42
43 /*!
44  * \file
45  * \brief SIP-router core :: 
46  * \ingroup core
47  * Module: \ref core
48  */
49
50
51 #include <string.h>
52 #include <stdlib.h>
53 #include <sys/time.h>
54
55 #include "receive.h"
56 #include "globals.h"
57 #include "dprint.h"
58 #include "route.h"
59 #include "parser/msg_parser.h"
60 #include "forward.h"
61 #include "action.h"
62 #include "mem/mem.h"
63 #include "stats.h"
64 #include "ip_addr.h"
65 #include "script_cb.h"
66 #include "nonsip_hooks.h"
67 #include "dset.h"
68 #include "usr_avp.h"
69 #ifdef WITH_XAVP
70 #include "xavp.h"
71 #endif
72 #include "select_buf.h"
73
74 #include "tcp_server.h" /* for tcpconn_add_alias */
75 #include "tcp_options.h" /* for access to tcp_accept_aliases*/
76 #include "cfg/cfg.h"
77 #include "core_stats.h"
78
79 #ifdef DEBUG_DMALLOC
80 #include <mem/dmalloc.h>
81 #endif
82
83 unsigned int msg_no=0;
84 /* address preset vars */
85 str default_global_address={0,0};
86 str default_global_port={0,0};
87 str default_via_address={0,0};
88 str default_via_port={0,0};
89
90 /**
91  * increment msg_no and return the new value
92  */
93 unsigned int inc_msg_no(void)
94 {
95         return ++msg_no;
96 }
97
98
99 /* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
100  * break (e.g.: modules/textops)
101  */
102 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
103 {
104         struct sip_msg* msg;
105         struct run_act_ctx ctx;
106         int ret;
107 #ifdef STATS
108         int skipped = 1;
109         struct timeval tvb, tve;        
110         struct timezone tz;
111         unsigned int diff;
112 #endif
113         str inb;
114
115         inb.s = buf;
116         inb.len = len;
117         sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
118         len = inb.len;
119
120         msg=pkg_malloc(sizeof(struct sip_msg));
121         if (msg==0) {
122                 LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
123                 goto error00;
124         }
125         msg_no++;
126         /* number of vias parsed -- good for diagnostic info in replies */
127         via_cnt=0;
128
129         memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
130         /* fill in msg */
131         msg->buf=buf;
132         msg->len=len;
133         /* zero termination (termination of orig message bellow not that
134            useful as most of the work is done with scratch-pad; -jiri  */
135         /* buf[len]=0; */ /* WARNING: zero term removed! */
136         msg->rcv=*rcv_info;
137         msg->id=msg_no;
138         msg->pid=my_pid();
139         msg->set_global_address=default_global_address;
140         msg->set_global_port=default_global_port;
141         
142         if(likely(sr_msg_time==1)) msg_set_time(msg);
143
144         if (parse_msg(buf,len, msg)!=0){
145                 LOG(cfg_get(core, core_cfg, corelog),
146                                 "core parsing of SIP message failed (%s:%d/%d)\n",
147                                 ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
148                                 (int)msg->rcv.proto);
149                 goto error02;
150         }
151         DBG("After parse_msg...\n");
152
153
154         /* ... clear branches from previous message */
155         clear_branches();
156
157         if (msg->first_line.type==SIP_REQUEST){
158                 ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
159                 if (!IS_SIP(msg)){
160                         if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
161                                 if (unlikely(ret==NONSIP_MSG_ERROR))
162                                         goto error03;
163                                 goto end; /* drop the message */
164                         }
165                 }
166                 /* sanity checks */
167                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
168                         /* no via, send back error ? */
169                         LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
170                         STATS_BAD_MSG();
171                         goto error02;
172                 }
173                 /* check if necessary to add receive?->moved to forward_req */
174                 /* check for the alias stuff */
175 #ifdef USE_TCP
176                 if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) && 
177                                 (((rcv_info->proto==PROTO_TCP) && !tcp_disable)
178 #ifdef USE_TLS
179                                         || ((rcv_info->proto==PROTO_TLS) && !tls_disable)
180 #endif
181                                 )
182                         ){
183                         if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
184                                                                         rcv_info->proto)!=0){
185                                 LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
186                                 /* continue */
187                         }
188                 }
189 #endif
190
191         /*      skip: */
192                 DBG("preparing to run routing scripts...\n");
193 #ifdef  STATS
194                 gettimeofday( & tvb, &tz );
195 #endif
196                 /* execute pre-script callbacks, if any; -jiri */
197                 /* if some of the callbacks said not to continue with
198                    script processing, don't do so
199                    if we are here basic sanity checks are already done
200                    (like presence of at least one via), so you can count
201                    on via1 being parsed in a pre-script callback --andrei
202                 */
203                 if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
204                 {
205                         STATS_REQ_FWD_DROP();
206                         goto end; /* drop the request */
207                 }
208
209                 set_route_type(REQUEST_ROUTE);
210                 /* exec the routing script */
211                 if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
212                         LOG(L_WARN, "WARNING: receive_msg: "
213                                         "error while trying script\n");
214                         goto error_req;
215                 }
216
217 #ifdef STATS
218                 gettimeofday( & tve, &tz );
219                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
220                 stats->processed_requests++;
221                 stats->acc_req_time += diff;
222                 DBG("successfully ran routing scripts...(%d usec)\n", diff);
223                 STATS_RX_REQUEST( msg->first_line.u.request.method_value );
224 #endif
225
226                 /* execute post request-script callbacks */
227                 exec_post_script_cb(msg, REQUEST_CB_TYPE);
228         }else if (msg->first_line.type==SIP_REPLY){
229                 /* sanity checks */
230                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
231                         /* no via, send back error ? */
232                         LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
233                         STATS_BAD_RPL();
234                         goto error02;
235                 }
236
237 #ifdef STATS
238                 gettimeofday( & tvb, &tz );
239                 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
240 #endif
241                 
242                 /* execute pre-script callbacks, if any; -jiri */
243                 /* if some of the callbacks said not to continue with
244                    script processing, don't do so
245                    if we are here basic sanity checks are already done
246                    (like presence of at least one via), so you can count
247                    on via1 being parsed in a pre-script callback --andrei
248                 */
249                 if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
250                 {
251                         STATS_RPL_FWD_DROP();
252                         goto end; /* drop the reply */
253                 }
254
255                 /* exec the onreply routing script */
256                 if (onreply_rt.rlist[DEFAULT_RT]){
257                         set_route_type(CORE_ONREPLY_ROUTE);
258                         ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
259 #ifndef NO_ONREPLY_ROUTE_ERROR
260                         if (unlikely(ret<0)){
261                                 LOG(L_WARN, "WARNING: receive_msg: "
262                                                 "error while trying onreply script\n");
263                                 goto error_rpl;
264                         }else
265 #endif /* NO_ONREPLY_ROUTE_ERROR */
266                         if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
267                                 STATS_RPL_FWD_DROP();
268                                 goto skip_send_reply; /* drop the message, no error */
269                         }
270                 }
271                 /* send the msg */
272                 forward_reply(msg);
273         skip_send_reply:
274 #ifdef STATS
275                 gettimeofday( & tve, &tz );
276                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
277                 stats->processed_responses++;
278                 stats->acc_res_time+=diff;
279                 DBG("successfully ran reply processing...(%d usec)\n", diff);
280 #endif
281
282                 /* execute post reply-script callbacks */
283                 exec_post_script_cb(msg, ONREPLY_CB_TYPE);
284         }
285
286 end:
287 #ifdef STATS
288         skipped = 0;
289 #endif
290         /* free possible loaded avps -bogdan */
291         reset_avps();
292 #ifdef WITH_XAVP
293         xavp_reset_list();
294 #endif
295         DBG("receive_msg: cleaning up\n");
296         free_sip_msg(msg);
297         pkg_free(msg);
298 #ifdef STATS
299         if (skipped) STATS_RX_DROPS;
300 #endif
301         return 0;
302 #ifndef NO_ONREPLY_ROUTE_ERROR
303 error_rpl:
304         /* execute post reply-script callbacks */
305         exec_post_script_cb(msg, ONREPLY_CB_TYPE);
306         reset_avps();
307 #ifdef WITH_XAVP
308         xavp_reset_list();
309 #endif
310         goto error02;
311 #endif /* NO_ONREPLY_ROUTE_ERROR */
312 error_req:
313         DBG("receive_msg: error:...\n");
314         /* execute post request-script callbacks */
315         exec_post_script_cb(msg, REQUEST_CB_TYPE);
316 error03:
317         /* free possible loaded avps -bogdan */
318         reset_avps();
319 #ifdef WITH_XAVP
320         xavp_reset_list();
321 #endif
322 error02:
323         free_sip_msg(msg);
324         pkg_free(msg);
325 error00:
326         STATS_RX_DROPS;
327         return -1;
328 }
329