core: receive - clang format the code
[sip-router] / src / core / 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 int _sr_ip_free_bind = 0;
64
65 unsigned int msg_no = 0;
66 /* address preset vars */
67 str default_global_address = {0, 0};
68 str default_global_port = {0, 0};
69 str default_via_address = {0, 0};
70 str default_via_port = {0, 0};
71
72 /**
73  * increment msg_no and return the new value
74  */
75 unsigned int inc_msg_no(void)
76 {
77         return ++msg_no;
78 }
79
80 /**
81  *
82  */
83 int sip_check_fline(char *buf, unsigned int len)
84 {
85         char *p;
86         int m;
87
88         m = 0;
89         for(p = buf; p < buf + len; p++) {
90                 /* first check if is a reply - starts with SIP/2.0 */
91                 if(m == 0) {
92                         if(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
93                                 continue;
94                         if(buf + len - p < 10)
95                                 return -1;
96                         if(strncmp(p, "SIP/2.0 ", 8) == 0) {
97                                 LM_DBG("first line indicates a SIP reply\n");
98                                 return 0;
99                         }
100                         m = 1;
101                 } else {
102                         /* check if a request - before end of first line is SIP/2.0 */
103                         if(*p != '\r' && *p != '\n')
104                                 continue;
105                         if(p - 10 >= buf) {
106                                 if(strncmp(p - 8, " SIP/2.0", 8) == 0) {
107                                         LM_DBG("first line indicates a SIP request\n");
108                                         return 0;
109                                 }
110                         }
111                         return -1;
112                 }
113         }
114         return -1;
115 }
116
117 /** Receive message
118  *  WARNING: buf must be 0 terminated (buf[len]=0) or some things might
119  * break (e.g.: modules/textops)
120  */
121 int receive_msg(char *buf, unsigned int len, struct receive_info *rcv_info)
122 {
123         struct sip_msg *msg;
124         struct run_act_ctx ctx;
125         struct run_act_ctx *bctx;
126         int ret;
127 #ifdef STATS
128         int skipped = 1;
129         int stats_on = 1;
130 #else
131         int stats_on = 0;
132 #endif
133         struct timeval tvb, tve;
134         struct timezone tz;
135         unsigned int diff = 0;
136         str inb;
137         sr_net_info_t netinfo;
138         sr_kemi_eng_t *keng = NULL;
139         sr_event_param_t evp = {0};
140
141         if(sr_event_enabled(SREV_NET_DATA_RECV)) {
142                 if(sip_check_fline(buf, len) == 0) {
143                         memset(&netinfo, 0, sizeof(sr_net_info_t));
144                         netinfo.data.s = buf;
145                         netinfo.data.len = len;
146                         netinfo.rcv = rcv_info;
147                         evp.data = (void *)&netinfo;
148                         sr_event_exec(SREV_NET_DATA_RECV, &evp);
149                 }
150         }
151
152         inb.s = buf;
153         inb.len = len;
154         evp.data = (void *)&inb;
155         evp.rcv = rcv_info;
156         sr_event_exec(SREV_NET_DATA_IN, &evp);
157         len = inb.len;
158
159         msg = pkg_malloc(sizeof(struct sip_msg));
160         if(msg == 0) {
161                 LM_ERR("no mem for sip_msg\n");
162                 goto error00;
163         }
164         msg_no++;
165         /* number of vias parsed -- good for diagnostic info in replies */
166         via_cnt = 0;
167
168         memset(msg, 0, sizeof(struct sip_msg)); /* init everything to 0 */
169         /* fill in msg */
170         msg->buf = buf;
171         msg->len = len;
172         /* zero termination (termination of orig message bellow not that
173          * useful as most of the work is done with scratch-pad; -jiri  */
174         /* buf[len]=0; */ /* WARNING: zero term removed! */
175         msg->rcv = *rcv_info;
176         msg->id = msg_no;
177         msg->pid = my_pid();
178         msg->set_global_address = default_global_address;
179         msg->set_global_port = default_global_port;
180
181         if(likely(sr_msg_time == 1))
182                 msg_set_time(msg);
183
184         if(parse_msg(buf, len, msg) != 0) {
185                 evp.data = (void *)msg;
186                 if((ret = sr_event_exec(SREV_RCV_NOSIP, &evp)) < NONSIP_MSG_DROP) {
187                         LOG(cfg_get(core, core_cfg, corelog),
188                                         "core parsing of SIP message failed (%s:%d/%d)\n",
189                                         ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
190                                         (int)msg->rcv.proto);
191                         sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
192                 } else if(ret == NONSIP_MSG_DROP)
193                         goto error02;
194         }
195
196         if(parse_headers(msg, HDR_FROM_F | HDR_TO_F | HDR_CALLID_F | HDR_CSEQ_F, 0)
197                         < 0) {
198                 LM_WARN("parsing relevant headers failed\n");
199         }
200         LM_DBG("--- received sip message - %s - call-id: [%.*s] - cseq: [%.*s]\n",
201                         (msg->first_line.type == SIP_REQUEST) ? "request" : "reply",
202                         (msg->callid && msg->callid->body.s) ? msg->callid->body.len : 0,
203                         (msg->callid && msg->callid->body.s) ? msg->callid->body.s : "",
204                         (msg->cseq && msg->cseq->body.s) ? msg->cseq->body.len : 0,
205                         (msg->cseq && msg->cseq->body.s) ? msg->cseq->body.s : "");
206
207         /* set log prefix */
208         log_prefix_set(msg);
209
210         /* ... clear branches from previous message */
211         clear_branches();
212
213         if(msg->first_line.type == SIP_REQUEST) {
214                 ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
215                 if(!IS_SIP(msg)) {
216                         if((ret = nonsip_msg_run_hooks(msg)) != NONSIP_MSG_ACCEPT) {
217                                 if(unlikely(ret == NONSIP_MSG_ERROR))
218                                         goto error03;
219                                 goto end; /* drop the message */
220                         }
221                 }
222                 /* sanity checks */
223                 if((msg->via1 == 0) || (msg->via1->error != PARSE_OK)) {
224                         /* no via, send back error ? */
225                         LM_ERR("no via found in request\n");
226                         STATS_BAD_MSG();
227                         goto error02;
228                 }
229 /* check if necessary to add receive?->moved to forward_req */
230 /* check for the alias stuff */
231 #ifdef USE_TCP
232                 if(msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases)
233                                 && (((rcv_info->proto == PROTO_TCP) && !tcp_disable)
234 #ifdef USE_TLS
235                                                    || ((rcv_info->proto == PROTO_TLS) && !tls_disable)
236 #endif
237                                                                    )) {
238                         if(tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
239                                            rcv_info->proto)
240                                         != 0) {
241                                 LM_ERR("tcp alias failed\n");
242                                 /* continue */
243                         }
244                 }
245 #endif
246
247                 /*      skip: */
248                 LM_DBG("preparing to run routing scripts...\n");
249                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
250                                 || stats_on == 1) {
251                         gettimeofday(&tvb, &tz);
252                 }
253                 /* execute pre-script callbacks, if any; -jiri */
254                 /* if some of the callbacks said not to continue with
255                  * script processing, don't do so
256                  * if we are here basic sanity checks are already done
257                  * (like presence of at least one via), so you can count
258                  * on via1 being parsed in a pre-script callback --andrei
259                 */
260                 if(exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0) {
261                         STATS_REQ_FWD_DROP();
262                         goto end; /* drop the request */
263                 }
264
265                 set_route_type(REQUEST_ROUTE);
266                 /* exec the routing script */
267                 if(unlikely(main_rt.rlist[DEFAULT_RT] == NULL)) {
268                         keng = sr_kemi_eng_get();
269                         if(keng == NULL) {
270                                 LM_ERR("no config routing engine registered\n");
271                                 goto error_req;
272                         }
273                         if(keng->froute(msg, REQUEST_ROUTE, NULL, NULL) < 0) {
274                                 LM_NOTICE("negative return code from engine function\n");
275                         }
276                 } else {
277                         if(run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0) < 0) {
278                                 LM_WARN("error while trying script\n");
279                                 goto error_req;
280                         }
281                 }
282
283                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
284                                 || stats_on == 1) {
285                         gettimeofday(&tve, &tz);
286                         diff = (tve.tv_sec - tvb.tv_sec) * 1000000
287                                    + (tve.tv_usec - tvb.tv_usec);
288                         LOG(cfg_get(core, core_cfg, latency_cfg_log),
289                                         "request-route executed in: %d usec\n", diff);
290 #ifdef STATS
291                         stats->processed_requests++;
292                         stats->acc_req_time += diff;
293                         STATS_RX_REQUEST(msg->first_line.u.request.method_value);
294 #endif
295                 }
296
297                 /* execute post request-script callbacks */
298                 exec_post_script_cb(msg, REQUEST_CB_TYPE);
299         } else if(msg->first_line.type == SIP_REPLY) {
300                 /* sanity checks */
301                 if((msg->via1 == 0) || (msg->via1->error != PARSE_OK)) {
302                         /* no via, send back error ? */
303                         LM_ERR("no via found in reply\n");
304                         STATS_BAD_RPL();
305                         goto error02;
306                 }
307
308                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
309                                 || stats_on == 1) {
310                         gettimeofday(&tvb, &tz);
311                 }
312 #ifdef STATS
313                 STATS_RX_RESPONSE(msg->first_line.u.reply.statuscode / 100);
314 #endif
315
316                 /* execute pre-script callbacks, if any; -jiri */
317                 /* if some of the callbacks said not to continue with
318                  * script processing, don't do so
319                  * if we are here basic sanity checks are already done
320                  * (like presence of at least one via), so you can count
321                  * on via1 being parsed in a pre-script callback --andrei
322                 */
323                 if(exec_pre_script_cb(msg, ONREPLY_CB_TYPE) == 0) {
324                         STATS_RPL_FWD_DROP();
325                         goto end; /* drop the reply */
326                 }
327
328                 /* exec the onreply routing script */
329                 keng = sr_kemi_eng_get();
330                 if(onreply_rt.rlist[DEFAULT_RT] != NULL || keng != NULL) {
331                         set_route_type(CORE_ONREPLY_ROUTE);
332                         ret = 1;
333                         if(unlikely(keng != NULL)) {
334                                 bctx = sr_kemi_act_ctx_get();
335                                 init_run_actions_ctx(&ctx);
336                                 sr_kemi_act_ctx_set(&ctx);
337                                 ret = keng->froute(msg, CORE_ONREPLY_ROUTE, NULL, NULL);
338                                 sr_kemi_act_ctx_set(bctx);
339                         } else {
340                                 ret = run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
341                         }
342 #ifndef NO_ONREPLY_ROUTE_ERROR
343                         if(unlikely(ret < 0)) {
344                                 LM_WARN("error while trying onreply script\n");
345                                 goto error_rpl;
346                         } else
347 #endif /* NO_ONREPLY_ROUTE_ERROR */
348                                         if(unlikely(ret == 0 || (ctx.run_flags & DROP_R_F))) {
349                                 STATS_RPL_FWD_DROP();
350                                 goto skip_send_reply; /* drop the message, no error */
351                         }
352                 }
353                 /* send the msg */
354                 forward_reply(msg);
355         skip_send_reply:
356                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
357                                 || stats_on == 1) {
358                         gettimeofday(&tve, &tz);
359                         diff = (tve.tv_sec - tvb.tv_sec) * 1000000
360                                    + (tve.tv_usec - tvb.tv_usec);
361                         LOG(cfg_get(core, core_cfg, latency_cfg_log),
362                                         "reply-route executed in: %d usec\n", diff);
363 #ifdef STATS
364                         stats->processed_responses++;
365                         stats->acc_res_time += diff;
366 #endif
367                 }
368
369                 /* execute post reply-script callbacks */
370                 exec_post_script_cb(msg, ONREPLY_CB_TYPE);
371         }
372
373 end:
374 #ifdef STATS
375         skipped = 0;
376 #endif
377         ksr_msg_env_reset();
378         LM_DBG("cleaning up\n");
379         free_sip_msg(msg);
380         pkg_free(msg);
381 #ifdef STATS
382         if(skipped)
383                 STATS_RX_DROPS;
384 #endif
385         /* reset log prefix */
386         log_prefix_set(NULL);
387         return 0;
388
389 #ifndef NO_ONREPLY_ROUTE_ERROR
390 error_rpl:
391         /* execute post reply-script callbacks */
392         exec_post_script_cb(msg, ONREPLY_CB_TYPE);
393         goto error02;
394 #endif /* NO_ONREPLY_ROUTE_ERROR */
395 error_req:
396         LM_DBG("error:...\n");
397         /* execute post request-script callbacks */
398         exec_post_script_cb(msg, REQUEST_CB_TYPE);
399 error03:
400 error02:
401         free_sip_msg(msg);
402         pkg_free(msg);
403 error00:
404         ksr_msg_env_reset();
405         STATS_RX_DROPS;
406         /* reset log prefix */
407         log_prefix_set(NULL);
408         return -1;
409 }
410
411 /**
412  * clean up msg environment, such as avp and xavp lists
413  */
414 void ksr_msg_env_reset(void)
415 {
416         reset_avps();
417 #ifdef WITH_XAVP
418         xavp_reset_list();
419 #endif
420 }