8ddf3e945b20cf5548b03993257b630906a5cd89
[sip-router] / receive.c
1 /*
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 /*!
23  * \file
24  * \brief Kamailio core ::
25  * \ingroup core
26  * Module: \ref core
27  */
28
29
30 #include <string.h>
31 #include <stdlib.h>
32 #include <sys/time.h>
33
34 #include "receive.h"
35 #include "globals.h"
36 #include "dprint.h"
37 #include "route.h"
38 #include "parser/msg_parser.h"
39 #include "forward.h"
40 #include "action.h"
41 #include "mem/mem.h"
42 #include "stats.h"
43 #include "ip_addr.h"
44 #include "script_cb.h"
45 #include "nonsip_hooks.h"
46 #include "dset.h"
47 #include "usr_avp.h"
48 #ifdef WITH_XAVP
49 #include "xavp.h"
50 #endif
51 #include "select_buf.h"
52
53 #include "tcp_server.h" /* for tcpconn_add_alias */
54 #include "tcp_options.h" /* for access to tcp_accept_aliases*/
55 #include "cfg/cfg.h"
56 #include "core_stats.h"
57 #include "kemi.h"
58
59 #ifdef DEBUG_DMALLOC
60 #include <mem/dmalloc.h>
61 #endif
62
63 unsigned int msg_no=0;
64 /* address preset vars */
65 str default_global_address={0,0};
66 str default_global_port={0,0};
67 str default_via_address={0,0};
68 str default_via_port={0,0};
69
70 /**
71  * increment msg_no and return the new value
72  */
73 unsigned int inc_msg_no(void)
74 {
75         return ++msg_no;
76 }
77
78 /**
79  *
80  */
81 int sip_check_fline(char* buf, unsigned int len)
82 {
83         char *p;
84         int m;
85
86         m = 0;
87         for(p=buf; p<buf+len; p++) {
88                 /* first check if is a reply - starts with SIP/2.0 */
89                 if(m==0) {
90                         if(*p==' ' || *p=='\t' || *p=='\r' || *p=='\n') continue;
91                         if(buf+len-p<10) return -1;
92                         if(strncmp(p, "SIP/2.0 ", 8)==0) {
93                                 LM_DBG("first line indicates a SIP reply\n");
94                                 return 0;
95                         }
96                         m=1;
97                 } else {
98                         /* check if a request - before end of first line is SIP/2.0 */
99                         if(*p!='\r' && *p!='\n') continue;
100                         if(p-10>=buf) {
101                                 if(strncmp(p-8, " SIP/2.0", 8)==0) {
102                                         LM_DBG("first line indicates a SIP request\n");
103                                         return 0;
104                                 }
105                         }
106                         return -1;
107                 }
108         }
109         return -1;
110 }
111
112 /** Receive message
113  *  WARNING: buf must be 0 terminated (buf[len]=0) or some things might
114  * break (e.g.: modules/textops)
115  */
116 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
117 {
118         struct sip_msg* msg;
119         struct run_act_ctx ctx;
120         struct run_act_ctx *bctx;
121         int ret;
122 #ifdef STATS
123         int skipped = 1;
124         int stats_on = 1;
125 #else
126         int stats_on = 0;
127 #endif
128         struct timeval tvb, tve;
129         struct timezone tz;
130         unsigned int diff = 0;
131         str inb;
132         sr_net_info_t netinfo;
133         sr_kemi_eng_t *keng = NULL;
134
135         if(sr_event_enabled(SREV_NET_DATA_RECV)) {
136                 if(sip_check_fline(buf, len)==0) {
137                         memset(&netinfo, 0, sizeof(sr_net_info_t));
138                         netinfo.data.s = buf;
139                         netinfo.data.len = len;
140                         netinfo.rcv = rcv_info;
141                         sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo);
142                 }
143         }
144
145         inb.s = buf;
146         inb.len = len;
147         sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
148         len = inb.len;
149
150         msg=pkg_malloc(sizeof(struct sip_msg));
151         if (msg==0) {
152                 LM_ERR("no mem for sip_msg\n");
153                 goto error00;
154         }
155         msg_no++;
156         /* number of vias parsed -- good for diagnostic info in replies */
157         via_cnt=0;
158
159         memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
160         /* fill in msg */
161         msg->buf=buf;
162         msg->len=len;
163         /* zero termination (termination of orig message bellow not that
164          * useful as most of the work is done with scratch-pad; -jiri  */
165         /* buf[len]=0; */ /* WARNING: zero term removed! */
166         msg->rcv=*rcv_info;
167         msg->id=msg_no;
168         msg->pid=my_pid();
169         msg->set_global_address=default_global_address;
170         msg->set_global_port=default_global_port;
171
172         if(likely(sr_msg_time==1)) msg_set_time(msg);
173
174         if (parse_msg(buf,len, msg)!=0){
175                 if((ret=sr_event_exec(SREV_RCV_NOSIP, (void*)msg))<NONSIP_MSG_DROP) {
176                         LOG(cfg_get(core, core_cfg, corelog),
177                                 "core parsing of SIP message failed (%s:%d/%d)\n",
178                                 ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
179                                 (int)msg->rcv.proto);
180                         sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
181                 }               
182                 else if(ret == NONSIP_MSG_DROP) goto error02;
183         }
184         LM_DBG("After parse_msg...\n");
185
186         /* set log prefix */
187         log_prefix_set(msg);
188
189         /* ... clear branches from previous message */
190         clear_branches();
191
192         if (msg->first_line.type==SIP_REQUEST){
193                 ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
194                 if (!IS_SIP(msg)){
195                         if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
196                                 if (unlikely(ret==NONSIP_MSG_ERROR))
197                                         goto error03;
198                                 goto end; /* drop the message */
199                         }
200                 }
201                 /* sanity checks */
202                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
203                         /* no via, send back error ? */
204                         LM_ERR("no via found in request\n");
205                         STATS_BAD_MSG();
206                         goto error02;
207                 }
208                 /* check if necessary to add receive?->moved to forward_req */
209                 /* check for the alias stuff */
210 #ifdef USE_TCP
211                 if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) &&
212                                 (((rcv_info->proto==PROTO_TCP) && !tcp_disable)
213 #ifdef USE_TLS
214                                         || ((rcv_info->proto==PROTO_TLS) && !tls_disable)
215 #endif
216                                 )
217                         ){
218                         if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
219                                                                         rcv_info->proto)!=0){
220                                 LM_ERR("tcp alias failed\n");
221                                 /* continue */
222                         }
223                 }
224 #endif
225
226         /*      skip: */
227                 LM_DBG("preparing to run routing scripts...\n");
228                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
229                                 || stats_on==1) {
230                         gettimeofday( & tvb, &tz );
231                 }
232                 /* execute pre-script callbacks, if any; -jiri */
233                 /* if some of the callbacks said not to continue with
234                  * script processing, don't do so
235                  * if we are here basic sanity checks are already done
236                  * (like presence of at least one via), so you can count
237                  * on via1 being parsed in a pre-script callback --andrei
238                 */
239                 if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
240                 {
241                         STATS_REQ_FWD_DROP();
242                         goto end; /* drop the request */
243                 }
244
245                 set_route_type(REQUEST_ROUTE);
246                 /* exec the routing script */
247                 if(unlikely(main_rt.rlist[DEFAULT_RT]==NULL)) {
248                         keng = sr_kemi_eng_get();
249                         if(keng==NULL) {
250                                 LM_ERR("no config routing engine registered\n");
251                                 goto error_req;
252                         }
253                         if(keng->froute(msg, REQUEST_ROUTE, NULL)<0) {
254                                 LM_NOTICE("negative return code from engine function\n");
255                         }
256                 } else {
257                         if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
258                                 LM_WARN("error while trying script\n");
259                                 goto error_req;
260                         }
261                 }
262
263                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
264                                 || stats_on==1) {
265                         gettimeofday( & tve, &tz );
266                         diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
267                         LOG(cfg_get(core, core_cfg, latency_cfg_log),
268                                         "request-route executed in: %d usec\n", diff);
269 #ifdef STATS
270                         stats->processed_requests++;
271                         stats->acc_req_time += diff;
272                         STATS_RX_REQUEST( msg->first_line.u.request.method_value );
273 #endif
274                 }
275
276                 /* execute post request-script callbacks */
277                 exec_post_script_cb(msg, REQUEST_CB_TYPE);
278         }else if (msg->first_line.type==SIP_REPLY){
279                 /* sanity checks */
280                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
281                         /* no via, send back error ? */
282                         LM_ERR("no via found in reply\n");
283                         STATS_BAD_RPL();
284                         goto error02;
285                 }
286
287                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
288                                 || stats_on==1) {
289                         gettimeofday( & tvb, &tz );
290                 }
291 #ifdef STATS
292                 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
293 #endif
294
295                 /* execute pre-script callbacks, if any; -jiri */
296                 /* if some of the callbacks said not to continue with
297                  * script processing, don't do so
298                  * if we are here basic sanity checks are already done
299                  * (like presence of at least one via), so you can count
300                  * on via1 being parsed in a pre-script callback --andrei
301                 */
302                 if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
303                 {
304                         STATS_RPL_FWD_DROP();
305                         goto end; /* drop the reply */
306                 }
307
308                 /* exec the onreply routing script */
309                 keng = sr_kemi_eng_get();
310                 if (onreply_rt.rlist[DEFAULT_RT]!=NULL || keng!=NULL){
311                         set_route_type(CORE_ONREPLY_ROUTE);
312                         ret = 1;
313                         if(unlikely(keng!=NULL)) {
314                                 bctx = sr_kemi_act_ctx_get();
315                                 init_run_actions_ctx(&ctx);
316                                 sr_kemi_act_ctx_set(&ctx);
317                                 ret = keng->froute(msg, CORE_ONREPLY_ROUTE, NULL);
318                                 sr_kemi_act_ctx_set(bctx);
319                         } else {
320                                 ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
321                         }
322 #ifndef NO_ONREPLY_ROUTE_ERROR
323                         if (unlikely(ret<0)){
324                                 LM_WARN("error while trying onreply script\n");
325                                 goto error_rpl;
326                         }else
327 #endif /* NO_ONREPLY_ROUTE_ERROR */
328                         if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
329                                 STATS_RPL_FWD_DROP();
330                                 goto skip_send_reply; /* drop the message, no error */
331                         }
332                 }
333                 /* send the msg */
334                 forward_reply(msg);
335         skip_send_reply:
336                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
337                                 || stats_on==1) {
338                         gettimeofday( & tve, &tz );
339                         diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
340                         LOG(cfg_get(core, core_cfg, latency_cfg_log),
341                                         "reply-route executed in: %d usec\n", diff);
342 #ifdef STATS
343                         stats->processed_responses++;
344                         stats->acc_res_time+=diff;
345 #endif
346                 }
347
348                 /* execute post reply-script callbacks */
349                 exec_post_script_cb(msg, ONREPLY_CB_TYPE);
350         }
351
352 end:
353 #ifdef STATS
354         skipped = 0;
355 #endif
356         /* free possible loaded avps -bogdan */
357         reset_avps();
358 #ifdef WITH_XAVP
359         xavp_reset_list();
360 #endif
361         LM_DBG("cleaning up\n");
362         free_sip_msg(msg);
363         pkg_free(msg);
364 #ifdef STATS
365         if (skipped) STATS_RX_DROPS;
366 #endif
367         /* reset log prefix */
368         log_prefix_set(NULL);
369         return 0;
370
371 #ifndef NO_ONREPLY_ROUTE_ERROR
372 error_rpl:
373         /* execute post reply-script callbacks */
374         exec_post_script_cb(msg, ONREPLY_CB_TYPE);
375         reset_avps();
376 #ifdef WITH_XAVP
377         xavp_reset_list();
378 #endif
379         goto error02;
380 #endif /* NO_ONREPLY_ROUTE_ERROR */
381 error_req:
382         LM_DBG("error:...\n");
383         /* execute post request-script callbacks */
384         exec_post_script_cb(msg, REQUEST_CB_TYPE);
385 error03:
386         /* free possible loaded avps -bogdan */
387         reset_avps();
388 #ifdef WITH_XAVP
389         xavp_reset_list();
390 #endif
391 error02:
392         free_sip_msg(msg);
393         pkg_free(msg);
394 error00:
395         STATS_RX_DROPS;
396         /* reset log prefix */
397         log_prefix_set(NULL);
398         return -1;
399 }
400