Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/receive.c
Line
Count
Source (jump to first uncovered line)
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 "ip_addr.h"
43
#include "script_cb.h"
44
#include "nonsip_hooks.h"
45
#include "dset.h"
46
#include "fmsg.h"
47
#include "usr_avp.h"
48
#include "xavp.h"
49
#include "select_buf.h"
50
#include "locking.h"
51
52
#include "tcp_server.h"  /* for tcpconn_add_alias */
53
#include "tcp_options.h" /* for access to tcp_accept_aliases*/
54
#include "cfg/cfg.h"
55
#include "core_stats.h"
56
#include "kemi.h"
57
58
#ifdef DEBUG_DMALLOC
59
#include <mem/dmalloc.h>
60
#endif
61
62
int _sr_ip_free_bind = 0;
63
64
unsigned int msg_no = 0;
65
/* address preset vars */
66
str default_global_address = {0, 0};
67
str default_global_port = {0, 0};
68
str default_via_address = {0, 0};
69
str default_via_port = {0, 0};
70
71
int ksr_route_locks_size = 0;
72
static rec_lock_set_t *ksr_route_locks_set = NULL;
73
74
int ksr_route_locks_set_init(void)
75
0
{
76
0
  if(ksr_route_locks_set != NULL || ksr_route_locks_size <= 0)
77
0
    return 0;
78
79
0
  ksr_route_locks_set = rec_lock_set_alloc(ksr_route_locks_size);
80
0
  if(ksr_route_locks_set == NULL) {
81
0
    LM_ERR("failed to allocate route locks set\n");
82
0
    return -1;
83
0
  }
84
0
  if(rec_lock_set_init(ksr_route_locks_set) == NULL) {
85
0
    LM_ERR("failed to init route locks set\n");
86
0
    return -1;
87
0
  }
88
0
  return 0;
89
0
}
90
91
void ksr_route_locks_set_destroy(void)
92
0
{
93
0
  if(ksr_route_locks_set == NULL)
94
0
    return;
95
96
0
  rec_lock_set_destroy(ksr_route_locks_set);
97
0
  rec_lock_set_dealloc(ksr_route_locks_set);
98
0
  ksr_route_locks_set = NULL;
99
0
}
100
101
/**
102
 * increment msg_no and return the new value
103
 */
104
unsigned int inc_msg_no(void)
105
0
{
106
0
  return ++msg_no;
107
0
}
108
109
/**
110
 *
111
 */
112
int sip_check_fline(char *buf, unsigned int len)
113
0
{
114
0
  char *p;
115
0
  int m;
116
117
0
  m = 0;
118
0
  for(p = buf; p < buf + len; p++) {
119
    /* first check if is a reply - starts with SIP/2.0 */
120
0
    if(m == 0) {
121
0
      if(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
122
0
        continue;
123
0
      if(buf + len - p < 10)
124
0
        return -1;
125
0
      if(strncmp(p, "SIP/2.0 ", 8) == 0) {
126
0
        LM_DBG("first line indicates a SIP reply\n");
127
0
        return 0;
128
0
      }
129
0
      m = 1;
130
0
    } else {
131
      /* check if a request - before end of first line is SIP/2.0 */
132
0
      if(*p != '\r' && *p != '\n')
133
0
        continue;
134
0
      if(p - 10 >= buf) {
135
0
        if(strncmp(p - 8, " SIP/2.0", 8) == 0) {
136
0
          LM_DBG("first line indicates a SIP request\n");
137
0
          return 0;
138
0
        }
139
0
      }
140
0
      return -1;
141
0
    }
142
0
  }
143
0
  return -1;
144
0
}
145
146
/**
147
 *
148
 */
149
static sr_net_info_t *ksr_evrt_rcvnetinfo = NULL;
150
int ksr_evrt_received_mode = 0;
151
str kemi_received_route_callback = STR_NULL;
152
153
/**
154
 *
155
 */
156
sr_net_info_t *ksr_evrt_rcvnetinfo_get(void)
157
0
{
158
0
  return ksr_evrt_rcvnetinfo;
159
0
}
160
161
/**
162
 *
163
 */
164
int ksr_evrt_received(char *buf, unsigned int *len, receive_info_t *rcv_info)
165
0
{
166
0
  sr_kemi_eng_t *keng = NULL;
167
0
  sr_net_info_t netinfo;
168
0
  int ret = 0;
169
0
  int rt = -1;
170
0
  run_act_ctx_t ra_ctx;
171
0
  run_act_ctx_t *bctx = NULL;
172
0
  sip_msg_t *fmsg = NULL;
173
0
  str evname = str_init("core:msg-received");
174
175
0
  if(len == 0 || rcv_info == NULL || buf == NULL) {
176
0
    LM_ERR("required parameters are not available\n");
177
0
    return -1;
178
0
  }
179
180
0
  if(kemi_received_route_callback.len > 0) {
181
0
    keng = sr_kemi_eng_get();
182
0
    if(keng == NULL) {
183
0
      LM_DBG("kemi enabled with no core:msg-receive event route "
184
0
           "callback\n");
185
0
      return 0;
186
0
    }
187
0
  } else {
188
0
    rt = route_lookup(&event_rt, evname.s);
189
0
    if(rt < 0 || event_rt.rlist[rt] == NULL) {
190
0
      LM_DBG("event route core:msg-received not defined\n");
191
0
      return 0;
192
0
    }
193
0
  }
194
0
  memset(&netinfo, 0, sizeof(sr_net_info_t));
195
0
  netinfo.data.s = buf;
196
0
  netinfo.data.len = *len;
197
0
  netinfo.bufsize = BUF_SIZE;
198
0
  netinfo.rcv = rcv_info;
199
200
0
  ksr_evrt_rcvnetinfo = &netinfo;
201
0
  set_route_type(REQUEST_ROUTE);
202
0
  fmsg = faked_msg_get_next();
203
0
  init_run_actions_ctx(&ra_ctx);
204
0
  if(keng) {
205
0
    bctx = sr_kemi_act_ctx_get();
206
0
    sr_kemi_act_ctx_set(&ra_ctx);
207
0
    ret = sr_kemi_route(
208
0
        keng, fmsg, REQUEST_ROUTE, &kemi_received_route_callback, NULL);
209
0
    sr_kemi_act_ctx_set(bctx);
210
0
  } else {
211
0
    ret = run_actions(&ra_ctx, event_rt.rlist[rt], fmsg);
212
0
  }
213
0
  if(ra_ctx.run_flags & DROP_R_F) {
214
0
    LM_DBG("dropping received message\n");
215
0
    ret = -1;
216
0
  }
217
0
  *len = netinfo.data.len;
218
0
  ksr_evrt_rcvnetinfo = NULL;
219
220
0
  return ret;
221
0
}
222
223
224
static int ksr_evrt_pre_routing_idx = -1;
225
str kemi_pre_routing_callback = STR_NULL;
226
227
228
/**
229
 *
230
 */
231
int ksr_evrt_pre_routing(sip_msg_t *msg)
232
0
{
233
0
  int ret = 0;
234
0
  int rt = -1;
235
0
  run_act_ctx_t ra_ctx;
236
0
  run_act_ctx_t *bctx = NULL;
237
0
  sr_kemi_eng_t *keng = NULL;
238
0
  str evname = str_init("core:pre-routing");
239
0
  recv_flags_t brflags;
240
241
0
  if(msg->rcv.rflags & RECV_F_INTERNAL) {
242
0
    DBG("skip internal routed message\n");
243
0
    return 0;
244
0
  }
245
246
0
  if(kemi_pre_routing_callback.len > 0) {
247
0
    keng = sr_kemi_eng_get();
248
0
    if(keng == NULL) {
249
0
      LM_DBG("kemi enabled with no core:pre-routing event route "
250
0
           "callback\n");
251
0
      return 0;
252
0
    }
253
0
  } else {
254
0
    if(ksr_evrt_pre_routing_idx == -1) {
255
0
      rt = route_lookup(&event_rt, evname.s);
256
0
      if(rt < 0 || event_rt.rlist[rt] == NULL) {
257
0
        ksr_evrt_pre_routing_idx = -2;
258
0
      }
259
0
    } else {
260
0
      rt = ksr_evrt_pre_routing_idx;
261
0
    }
262
0
    if(rt < 0 || event_rt.rlist[rt] == NULL) {
263
0
      LM_DBG("event route core:pre-routing not defined\n");
264
0
      return 0;
265
0
    }
266
0
  }
267
268
0
  set_route_type(REQUEST_ROUTE);
269
0
  init_run_actions_ctx(&ra_ctx);
270
0
  brflags = msg->rcv.rflags;
271
0
  msg->rcv.rflags |= RECV_F_PREROUTING;
272
0
  if(keng) {
273
0
    bctx = sr_kemi_act_ctx_get();
274
0
    sr_kemi_act_ctx_set(&ra_ctx);
275
0
    ret = sr_kemi_route(
276
0
        keng, msg, REQUEST_ROUTE, &kemi_pre_routing_callback, &evname);
277
0
    sr_kemi_act_ctx_set(bctx);
278
0
  } else {
279
0
    ret = run_actions(&ra_ctx, event_rt.rlist[rt], msg);
280
0
  }
281
0
  msg->rcv.rflags = brflags;
282
0
  if(ra_ctx.run_flags & DROP_R_F) {
283
0
    LM_DBG("drop was used\n");
284
0
    return 1;
285
0
  }
286
0
  LM_DBG("execution returned %d\n", ret);
287
288
0
  return 0;
289
0
}
290
291
/** Receive message
292
 *  WARNING: buf must be 0 terminated (buf[len]=0) or some things might
293
 * break (e.g.: modules/textops)
294
 */
295
int receive_msg(char *buf, unsigned int len, receive_info_t *rcv_info)
296
0
{
297
0
  struct sip_msg *msg = NULL;
298
0
  struct run_act_ctx ctx;
299
0
  struct run_act_ctx *bctx = NULL;
300
0
  int ret = -1;
301
0
  struct timeval tvb = {0}, tve = {0};
302
0
  unsigned int diff = 0;
303
0
  str inb = STR_NULL;
304
0
  sr_net_info_t netinfo = {0};
305
0
  sr_kemi_eng_t *keng = NULL;
306
0
  sr_event_param_t evp = {0};
307
0
  unsigned int cidlockidx = 0;
308
0
  unsigned int cidlockset = 0;
309
0
  int errsipmsg = 0;
310
0
  int exectime = 0;
311
312
0
  if(rcv_info->bind_address == NULL) {
313
0
    LM_ERR("critical - incoming message without local socket [%.*s ...]\n",
314
0
        (len > 128) ? 128 : len, buf);
315
0
    return -1;
316
0
  }
317
318
0
  if(ksr_evrt_received_mode != 0) {
319
0
    if(ksr_evrt_received(buf, &len, rcv_info) < 0) {
320
0
      LM_DBG("dropping the received message\n");
321
0
      goto error00;
322
0
    }
323
0
  }
324
0
  if(sr_event_enabled(SREV_NET_DATA_RECV)) {
325
0
    if(sip_check_fline(buf, len) == 0) {
326
0
      memset(&netinfo, 0, sizeof(sr_net_info_t));
327
0
      netinfo.data.s = buf;
328
0
      netinfo.data.len = len;
329
0
      netinfo.rcv = rcv_info;
330
0
      evp.data = (void *)&netinfo;
331
0
      sr_event_exec(SREV_NET_DATA_RECV, &evp);
332
0
    }
333
0
  }
334
335
0
  inb.s = buf;
336
0
  inb.len = len;
337
0
  evp.data = (void *)&inb;
338
0
  evp.rcv = rcv_info;
339
0
  sr_event_exec(SREV_NET_DATA_IN, &evp);
340
0
  len = inb.len;
341
342
0
  msg = pkg_malloc(sizeof(struct sip_msg));
343
0
  if(unlikely(msg == 0)) {
344
0
    PKG_MEM_ERROR;
345
0
    goto error00;
346
0
  }
347
0
  msg_no++;
348
  /* number of vias parsed -- good for diagnostic info in replies */
349
0
  via_cnt = 0;
350
351
0
  memset(msg, 0, sizeof(struct sip_msg)); /* init everything to 0 */
352
  /* fill in msg */
353
0
  msg->buf = buf;
354
0
  msg->len = len;
355
  /* zero termination (termination of orig message below not that
356
   * useful as most of the work is done with scratch-pad; -jiri  */
357
  /* buf[len]=0; */ /* WARNING: zero term removed! */
358
0
  msg->rcv = *rcv_info;
359
0
  msg->id = msg_no;
360
0
  msg->pid = my_pid();
361
0
  msg->set_global_address = default_global_address;
362
0
  msg->set_global_port = default_global_port;
363
364
0
  if(likely(sr_msg_time == 1))
365
0
    msg_set_time(msg);
366
367
0
  if(parse_msg(buf, len, msg) != 0) {
368
0
    errsipmsg = 1;
369
0
    evp.data = (void *)msg;
370
0
    if((ret = sr_event_exec(SREV_RCV_NOSIP, &evp)) < NONSIP_MSG_DROP) {
371
0
      LM_DBG("attempt of nonsip message processing failed\n");
372
0
    } else if(ret == NONSIP_MSG_DROP) {
373
0
      LM_DBG("nonsip message processing completed\n");
374
0
      goto end;
375
0
    }
376
0
  }
377
0
  if(errsipmsg == 1) {
378
0
    LOG(cfg_get(core, core_cfg, sip_parser_log),
379
0
        "core parsing of SIP message failed (%s:%d/%d)\n",
380
0
        ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
381
0
        (int)msg->rcv.proto);
382
0
    sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
383
0
    goto error02;
384
0
  }
385
386
0
  if(unlikely(parse_headers(msg,
387
0
            HDR_FROM_F | HDR_TO_F | HDR_CALLID_F | HDR_CSEQ_F, 0)
388
0
        < 0)) {
389
0
    LOG(cfg_get(core, core_cfg, sip_parser_log),
390
0
        "parsing relevant headers failed\n");
391
0
  }
392
0
  LM_DBG("--- received sip message - %s - call-id: [%.*s] - cseq: [%.*s]\n",
393
0
      (msg->first_line.type == SIP_REQUEST) ? "request" : "reply",
394
0
      (msg->callid && msg->callid->body.s) ? msg->callid->body.len : 0,
395
0
      (msg->callid && msg->callid->body.s) ? msg->callid->body.s : "",
396
0
      (msg->cseq && msg->cseq->body.s) ? msg->cseq->body.len : 0,
397
0
      (msg->cseq && msg->cseq->body.s) ? msg->cseq->body.s : "");
398
399
  /* set log prefix */
400
0
  log_prefix_set(msg);
401
402
  /* ... clear branches from previous message */
403
0
  clear_branches();
404
405
0
  ret = ksr_evrt_pre_routing(msg);
406
0
  if(ret < 0) {
407
0
    goto error02;
408
0
  }
409
0
  if(ret == 1) {
410
    /* finished */
411
0
    goto end;
412
0
  }
413
414
0
  if(unlikely(ksr_route_locks_set != NULL && msg->callid
415
0
        && msg->callid->body.s && msg->callid->body.len > 0)) {
416
0
    cidlockidx = get_hash1_raw(msg->callid->body.s, msg->callid->body.len);
417
0
    cidlockidx = cidlockidx % ksr_route_locks_set->size;
418
0
    cidlockset = 1;
419
0
  }
420
421
422
0
  if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))) {
423
0
    exectime = 1;
424
0
  }
425
426
0
  if(msg->first_line.type == SIP_REQUEST) {
427
0
    ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
428
0
    if(!IS_SIP(msg)) {
429
0
      LM_DBG("handling non-sip request message\n");
430
0
      if((ret = nonsip_msg_run_hooks(msg)) != NONSIP_MSG_ACCEPT) {
431
0
        if(unlikely(ret == NONSIP_MSG_ERROR)) {
432
0
          LM_DBG("failed handling non-sip request message\n");
433
0
          goto error03;
434
0
        }
435
0
        LM_DBG("finished handling non-sip request message\n");
436
0
        goto end; /* drop the message */
437
0
      }
438
0
    }
439
    /* sanity checks */
440
0
    if(unlikely((msg->via1 == 0) || (msg->via1->error != PARSE_OK))) {
441
      /* no via, send back error ? */
442
0
      LOG(cfg_get(core, core_cfg, sip_parser_log),
443
0
          "no via found in request\n");
444
0
      STATS_BAD_MSG();
445
0
      goto error02;
446
0
    }
447
0
    if(unlikely((msg->callid == 0) || (msg->cseq == 0) || (msg->from == 0)
448
0
          || (msg->to == 0))) {
449
      /* no required headers -- send back error ? */
450
0
      LOG(cfg_get(core, core_cfg, sip_parser_log),
451
0
          "required headers not found in request\n");
452
0
      STATS_BAD_MSG();
453
0
      goto error02;
454
0
    }
455
/* check if necessary to add receive?->moved to forward_req */
456
/* check for the alias stuff */
457
0
#ifdef USE_TCP
458
0
    if(msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases)
459
0
        && (((rcv_info->proto == PROTO_TCP) && !tcp_disable)
460
0
#ifdef USE_TLS
461
0
            || ((rcv_info->proto == PROTO_TLS) && !tls_disable)
462
0
#endif
463
0
                )) {
464
0
      if(tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
465
0
             rcv_info->proto)
466
0
          != 0) {
467
0
        LM_ERR("tcp alias failed\n");
468
        /* continue */
469
0
      }
470
0
    }
471
0
#endif
472
473
    /*  skip: */
474
0
    LM_DBG("preparing to run routing scripts...\n");
475
0
    if(exectime) {
476
0
      gettimeofday(&tvb, NULL);
477
0
    }
478
    /* execute pre-script callbacks, if any; -jiri */
479
    /* if some of the callbacks said not to continue with
480
     * script processing, don't do so
481
     * if we are here basic sanity checks are already done
482
     * (like presence of at least one via), so you can count
483
     * on via1 being parsed in a pre-script callback --andrei
484
    */
485
0
    if(exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0) {
486
0
      STATS_REQ_FWD_DROP();
487
0
      goto end; /* drop the request */
488
0
    }
489
490
0
    set_route_type(REQUEST_ROUTE);
491
    /* exec the routing script */
492
0
    if(unlikely(main_rt.rlist[DEFAULT_RT] == NULL)) {
493
0
      keng = sr_kemi_eng_get();
494
0
      if(keng == NULL) {
495
0
        LM_ERR("no request_route {...} and no other config routing"
496
0
             " engine registered\n");
497
0
        goto error_req;
498
0
      }
499
0
      if(unlikely(cidlockset)) {
500
0
        rec_lock_set_get(ksr_route_locks_set, cidlockidx);
501
0
        if(sr_kemi_route(keng, msg, REQUEST_ROUTE, NULL, NULL) < 0)
502
0
          LM_NOTICE("negative return code from engine function\n");
503
0
        rec_lock_set_release(ksr_route_locks_set, cidlockidx);
504
0
      } else {
505
0
        if(sr_kemi_route(keng, msg, REQUEST_ROUTE, NULL, NULL) < 0)
506
0
          LM_NOTICE("negative return code from engine function\n");
507
0
      }
508
0
    } else {
509
0
      if(unlikely(cidlockset)) {
510
0
        rec_lock_set_get(ksr_route_locks_set, cidlockidx);
511
0
        if(run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0) < 0) {
512
0
          rec_lock_set_release(ksr_route_locks_set, cidlockidx);
513
0
          LM_WARN("error while trying script\n");
514
0
          goto error_req;
515
0
        }
516
0
        rec_lock_set_release(ksr_route_locks_set, cidlockidx);
517
0
      } else {
518
0
        if(run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0) < 0) {
519
0
          LM_WARN("error while trying script\n");
520
0
          goto error_req;
521
0
        }
522
0
      }
523
0
    }
524
525
0
    if(exectime) {
526
0
      gettimeofday(&tve, NULL);
527
0
      diff = (tve.tv_sec - tvb.tv_sec) * 1000000
528
0
           + (tve.tv_usec - tvb.tv_usec);
529
0
      if(cfg_get(core, core_cfg, latency_limit_cfg) == 0
530
0
          || cfg_get(core, core_cfg, latency_limit_cfg) <= diff) {
531
0
        LOG(cfg_get(core, core_cfg, latency_cfg_log),
532
0
            "request-route executed in: %d usec\n", diff);
533
0
      }
534
0
    }
535
536
    /* execute post request-script callbacks */
537
0
    exec_post_script_cb(msg, REQUEST_CB_TYPE);
538
0
  } else if(msg->first_line.type == SIP_REPLY) {
539
    /* sanity checks */
540
0
    if((msg->via1 == 0) || (msg->via1->error != PARSE_OK)) {
541
      /* no via, send back error ? */
542
0
      LM_ERR("no via found in reply\n");
543
0
      STATS_BAD_RPL();
544
0
      goto error02;
545
0
    }
546
0
    if(unlikely((msg->callid == 0) || (msg->cseq == 0) || (msg->from == 0)
547
0
          || (msg->to == 0))) {
548
      /* no required headers -- send back error ? */
549
0
      LOG(cfg_get(core, core_cfg, sip_parser_log),
550
0
          "required headers not found in reply\n");
551
0
      STATS_BAD_RPL();
552
0
      goto error02;
553
0
    }
554
555
0
    if(exectime) {
556
0
      gettimeofday(&tvb, NULL);
557
0
    }
558
559
    /* execute pre-script callbacks, if any; -jiri */
560
    /* if some of the callbacks said not to continue with
561
     * script processing, don't do so
562
     * if we are here basic sanity checks are already done
563
     * (like presence of at least one via), so you can count
564
     * on via1 being parsed in a pre-script callback --andrei
565
    */
566
0
    if(exec_pre_script_cb(msg, ONREPLY_CB_TYPE) == 0) {
567
0
      STATS_RPL_FWD_DROP();
568
0
      goto end; /* drop the reply */
569
0
    }
570
571
    /* exec the onreply routing script */
572
0
    if(kemi_reply_route_callback.len > 0) {
573
0
      keng = sr_kemi_eng_get();
574
0
    }
575
0
    if(onreply_rt.rlist[DEFAULT_RT] != NULL || keng != NULL) {
576
0
      set_route_type(CORE_ONREPLY_ROUTE);
577
0
      ret = 1;
578
0
      if(unlikely(keng != NULL)) {
579
0
        bctx = sr_kemi_act_ctx_get();
580
0
        init_run_actions_ctx(&ctx);
581
0
        sr_kemi_act_ctx_set(&ctx);
582
0
        if(unlikely(cidlockset)) {
583
0
          rec_lock_set_get(ksr_route_locks_set, cidlockidx);
584
0
          ret = sr_kemi_route(
585
0
              keng, msg, CORE_ONREPLY_ROUTE, NULL, NULL);
586
0
          rec_lock_set_release(ksr_route_locks_set, cidlockidx);
587
0
        } else {
588
0
          ret = sr_kemi_route(
589
0
              keng, msg, CORE_ONREPLY_ROUTE, NULL, NULL);
590
0
        }
591
0
        sr_kemi_act_ctx_set(bctx);
592
0
      } else {
593
0
        if(unlikely(cidlockset)) {
594
0
          rec_lock_set_get(ksr_route_locks_set, cidlockidx);
595
0
          ret = run_top_route(
596
0
              onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
597
0
          rec_lock_set_release(ksr_route_locks_set, cidlockidx);
598
0
        } else {
599
0
          ret = run_top_route(
600
0
              onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
601
0
        }
602
0
      }
603
0
#ifndef NO_ONREPLY_ROUTE_ERROR
604
0
      if(unlikely(ret < 0)) {
605
0
        LM_WARN("error while trying onreply script\n");
606
0
        goto error_rpl;
607
0
      } else
608
0
#endif /* NO_ONREPLY_ROUTE_ERROR */
609
0
        if(unlikely(ret == 0 || (ctx.run_flags & DROP_R_F))) {
610
0
          STATS_RPL_FWD_DROP();
611
0
          LM_DBG("drop flag set - skip forwarding the reply\n");
612
0
          goto skip_send_reply; /* drop the message, no error */
613
0
        }
614
0
    }
615
    /* send the msg */
616
0
    forward_reply(msg);
617
0
  skip_send_reply:
618
0
    if(exectime) {
619
0
      gettimeofday(&tve, NULL);
620
0
      diff = (tve.tv_sec - tvb.tv_sec) * 1000000
621
0
           + (tve.tv_usec - tvb.tv_usec);
622
0
      if(cfg_get(core, core_cfg, latency_limit_cfg) == 0
623
0
          || cfg_get(core, core_cfg, latency_limit_cfg) <= diff) {
624
0
        LOG(cfg_get(core, core_cfg, latency_cfg_log),
625
0
            "reply-route executed in: %d usec\n", diff);
626
0
      }
627
0
    }
628
629
    /* execute post reply-script callbacks */
630
0
    exec_post_script_cb(msg, ONREPLY_CB_TYPE);
631
0
  }
632
633
0
end:
634
0
  ksr_msg_env_reset();
635
0
  LM_DBG("cleaning up\n");
636
0
  free_sip_msg(msg);
637
0
  pkg_free(msg);
638
  /* reset log prefix */
639
0
  log_prefix_set(NULL);
640
0
  return 0;
641
642
0
#ifndef NO_ONREPLY_ROUTE_ERROR
643
0
error_rpl:
644
  /* execute post reply-script callbacks */
645
0
  exec_post_script_cb(msg, ONREPLY_CB_TYPE);
646
0
  goto error02;
647
0
#endif /* NO_ONREPLY_ROUTE_ERROR */
648
0
error_req:
649
0
  LM_DBG("error:...\n");
650
  /* execute post request-script callbacks */
651
0
  exec_post_script_cb(msg, REQUEST_CB_TYPE);
652
0
error03:
653
0
error02:
654
0
  free_sip_msg(msg);
655
0
  pkg_free(msg);
656
0
error00:
657
0
  ksr_msg_env_reset();
658
  /* reset log prefix */
659
0
  log_prefix_set(NULL);
660
0
  return -1;
661
0
}
662
663
/**
664
 * clean up msg environment, such as avp, xavp and xavu lists
665
 */
666
void ksr_msg_env_reset(void)
667
0
{
668
0
  reset_avps();
669
0
  xavp_reset_list();
670
0
  xavu_reset_list();
671
0
  xavi_reset_list();
672
0
}