siptrace: check if a request is set to avoid local transaction crash
[kamailio] / src / modules / siptrace / siptrace.c
1 /*
2  * siptrace module - helper module to trace sip messages
3  *
4  * Copyright (C) 2006 Voice Sistem S.R.L.
5  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
6  *
7  * This file is part of Kamailio, a free SIP server.
8  *
9  * Kamailio is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * Kamailio is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 /*! \file
26  * siptrace module - helper module to trace sip messages
27  *
28  */
29
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 #include "../../core/sr_module.h"
36 #include "../../core/mod_fix.h"
37 #include "../../core/dprint.h"
38 #include "../../core/ut.h"
39 #include "../../core/ip_addr.h"
40 #include "../../core/mem/mem.h"
41 #include "../../core/mem/shm_mem.h"
42 #include "../../core/rpc.h"
43 #include "../../core/rpc_lookup.h"
44 #include "../../lib/srdb1/db.h"
45 #include "../../core/parser/parse_content.h"
46 #include "../../core/parser/parse_from.h"
47 #include "../../core/parser/parse_cseq.h"
48 #include "../../core/pvar.h"
49 #include "../../modules/tm/tm_load.h"
50 #include "../../modules/sl/sl.h"
51 #include "../../modules/dialog/dlg_load.h"
52 #include "../../core/str.h"
53 #include "../../core/onsend.h"
54 #include "../../core/events.h"
55 #include "../../core/kemi.h"
56
57 #include "siptrace_data.h"
58 #include "siptrace_hep.h"
59 #include "siptrace_send.h"
60
61 MODULE_VERSION
62
63 #define SIPTRACE_ANYADDR "any:255.255.255.255:5060"
64 #define SIPTRACE_ANYADDR_LEN (sizeof(SIPTRACE_ANYADDR) - 1)
65
66 struct tm_binds tmb;
67 struct dlg_binds dlgb;
68
69 /** SL API structure */
70 sl_api_t slb;
71
72 /* module function prototypes */
73 static int mod_init(void);
74 static int siptrace_init_rpc(void);
75 static int child_init(int rank);
76 static void destroy(void);
77 static int sip_trace(sip_msg_t *msg, dest_info_t *, str *, char *);
78 static int w_sip_trace0(struct sip_msg *, char *p1, char *p2);
79 static int w_sip_trace1(struct sip_msg *, char *dest);
80 static int w_sip_trace2(struct sip_msg *, char *dest, char *correlation_id);
81 static int w_sip_trace3(struct sip_msg *, char *dest, char *correlation_id, char *trace_type);
82 static int fixup_siptrace(void **param, int param_no);
83
84 static int parse_siptrace_uri(str* duri, dest_info_t* dst);
85 static enum siptrace_type_t parse_siptrace_flag(str* sflags);
86
87 static int w_hlog1(struct sip_msg *, char *message, char *);
88 static int w_hlog2(struct sip_msg *, char *correlationid, char *message);
89
90 static int sip_trace_store_db(siptrace_data_t *sto);
91
92 static void trace_onreq_out(struct cell *t, int type, struct tmcb_params *ps);
93 static void trace_onreply_in(struct cell *t, int type, struct tmcb_params *ps);
94 static void trace_onreply_out(struct cell *t, int type, struct tmcb_params *ps);
95 static void trace_tm_neg_ack_in(struct cell *t, int type, struct tmcb_params *ps);
96 static void trace_sl_onreply_out(sl_cbp_t *slcb);
97 static void trace_sl_ack_in(sl_cbp_t *slcb);
98
99
100
101 static void trace_transaction(sip_msg_t* msg, siptrace_info_t* info, int register_free_func);
102 static void trace_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params *params);
103 static void trace_dialog_transaction(struct dlg_cell* dlg, int type, struct dlg_cb_params *params);
104 static void free_trace_info(void* trace_info);
105 static int  serialize_siptrace_info(siptrace_info_t* info, str* serial_data);
106
107 int siptrace_net_data_recv(sr_event_param_t *evp);
108 int siptrace_net_data_send(sr_event_param_t *evp);
109 static int _siptrace_mode = 0;
110
111
112 static str db_url = str_init(DEFAULT_DB_URL);
113 static str siptrace_table = str_init("sip_trace");
114 static str date_column = str_init("time_stamp");                 /* 00 */
115 static str callid_column = str_init("callid");                   /* 01 */
116 static str traced_user_column = str_init("traced_user"); /* 02 */
117 static str msg_column = str_init("msg");                                 /* 03 */
118 static str method_column = str_init("method");                   /* 04 */
119 static str status_column = str_init("status");                   /* 05 */
120 static str fromip_column = str_init("fromip");                   /* 06 */
121 static str toip_column = str_init("toip");                               /* 07 */
122 static str fromtag_column = str_init("fromtag");                 /* 08 */
123 static str direction_column = str_init("direction");     /* 09 */
124 static str time_us_column = str_init("time_us");                 /* 10 */
125 static str totag_column = str_init("totag");                     /* 11 */
126
127 static str siptrace_info_dlgkey = str_init("__siptrace_info_dlg_key__");
128 static str siptrace_info_avp_str = str_init("$avp(__siptrace_info_avp__)");
129
130 #define NR_KEYS 12
131 #define SIP_TRACE_TABLE_VERSION 4
132
133 int trace_flag = 0;
134 int trace_on = 0;
135 int trace_sl_acks = 1;
136
137 int trace_to_database = 1;
138 int trace_delayed = 0;
139
140 int hep_version = 1;
141 int hep_capture_id = 1;
142 int hep_vendor_id = 0;
143 str auth_key_str = {0, 0};
144
145 int xheaders_write = 0;
146 int xheaders_read = 0;
147
148 str force_send_sock_str = {0, 0};
149 struct sip_uri *force_send_sock_uri = 0;
150
151 str dup_uri_str = {0, 0};
152 struct sip_uri *dup_uri = 0;
153
154 int *trace_on_flag = NULL;
155 int *trace_to_database_flag = NULL;
156
157 int *xheaders_write_flag = NULL;
158 int *xheaders_read_flag = NULL;
159
160 static unsigned short traced_user_avp_type = 0;
161 static int_str traced_user_avp;
162 static str traced_user_avp_str = {NULL, 0};
163
164 static unsigned short trace_table_avp_type = 0;
165 static int_str trace_table_avp;
166 static str trace_table_avp_str = {NULL, 0};
167
168 static unsigned short siptrace_info_avp_type = 0;
169 static int_str siptrace_info_avp;
170
171 static str trace_local_ip = {NULL, 0};
172
173 int hep_mode_on = 0;
174
175 db1_con_t *db_con = NULL; /*!< database connection */
176 db_func_t db_funcs;               /*!< Database functions */
177
178 /*! \brief
179  * Exported functions
180  */
181 static cmd_export_t cmds[] = {
182         {"sip_trace", (cmd_function)w_sip_trace0, 0, 0, 0,
183                 ANY_ROUTE},
184         {"sip_trace", (cmd_function)w_sip_trace1, 1, fixup_siptrace, 0,
185                 ANY_ROUTE},
186         {"sip_trace", (cmd_function)w_sip_trace2, 2, fixup_siptrace, 0,
187                 ANY_ROUTE},
188         {"sip_trace", (cmd_function)w_sip_trace3, 3, fixup_siptrace, 0,
189                 ANY_ROUTE},
190         {"hlog", (cmd_function)w_hlog1, 1, fixup_spve_null, 0,
191                 ANY_ROUTE},
192         {"hlog", (cmd_function)w_hlog2, 2, fixup_spve_spve, 0,
193                 ANY_ROUTE},
194         {0, 0, 0, 0, 0, 0}
195 };
196
197
198 /*! \brief
199  * Exported parameters
200  */
201 static param_export_t params[] = {
202         {"auth_key", PARAM_STR, &auth_key_str},
203         {"db_url", PARAM_STR, &db_url}, {"table", PARAM_STR, &siptrace_table},
204         {"date_column", PARAM_STR, &date_column},
205         {"callid_column", PARAM_STR, &callid_column},
206         {"traced_user_column", PARAM_STR, &traced_user_column},
207         {"msg_column", PARAM_STR, &msg_column},
208         {"method_column", PARAM_STR, &method_column},
209         {"status_column", PARAM_STR, &status_column},
210         {"fromip_column", PARAM_STR, &fromip_column},
211         {"toip_column", PARAM_STR, &toip_column},
212         {"fromtag_column", PARAM_STR, &fromtag_column},
213         {"totag_column", PARAM_STR, &totag_column},
214         {"direction_column", PARAM_STR, &direction_column},
215         {"trace_flag", INT_PARAM, &trace_flag},
216         {"trace_on", INT_PARAM, &trace_on},
217         {"traced_user_avp", PARAM_STR, &traced_user_avp_str},
218         {"trace_table_avp", PARAM_STR, &trace_table_avp_str},
219         {"duplicate_uri", PARAM_STR, &dup_uri_str},
220         {"trace_to_database", INT_PARAM, &trace_to_database},
221         {"trace_local_ip", PARAM_STR, &trace_local_ip},
222         {"trace_sl_acks", INT_PARAM, &trace_sl_acks},
223         {"xheaders_write", INT_PARAM, &xheaders_write},
224         {"xheaders_read", INT_PARAM, &xheaders_read},
225         {"hep_mode_on", INT_PARAM, &hep_mode_on},
226         {"force_send_sock", PARAM_STR, &force_send_sock_str},
227         {"hep_version", INT_PARAM, &hep_version},
228         {"hep_capture_id", INT_PARAM, &hep_capture_id},
229         {"trace_delayed", INT_PARAM, &trace_delayed},
230         {"trace_mode", PARAM_INT, &_siptrace_mode}, {0, 0, 0}
231 };
232
233 #ifdef STATISTICS
234 stat_var *siptrace_req;
235 stat_var *siptrace_rpl;
236
237 stat_export_t siptrace_stats[] = {
238         {"traced_requests", 0, &siptrace_req},
239         {"traced_replies", 0, &siptrace_rpl}, {0, 0, 0}
240 };
241 #endif
242
243 /*! \brief module exports */
244 struct module_exports exports = {
245         "siptrace",     /*!< module name */
246         DEFAULT_DLFLAGS, /*!< dlopen flags */
247         cmds,                   /*!< exported functions */
248         params,                 /*!< exported parameters */
249         0,                              /*!< exported rpc functions */
250         0,                              /*!< exported pseudo-variables */
251         0,                              /*!< response function */
252         mod_init,               /*!< module initialization function */
253         child_init,             /*!< child initialization function */
254         destroy                 /*!< destroy function */
255 };
256
257
258 /*! \brief Initialize siptrace module */
259 static int mod_init(void)
260 {
261         pv_spec_t avp_spec;
262         sl_cbelem_t slcb;
263
264 #ifdef STATISTICS
265         /* register statistics */
266         if(register_module_stats(exports.name, siptrace_stats) != 0) {
267                 LM_ERR("failed to register core statistics\n");
268                 return -1;
269         }
270 #endif
271
272         if(siptrace_init_rpc() != 0) {
273                 LM_ERR("failed to register RPC commands\n");
274                 return -1;
275         }
276
277         if(trace_flag < 0 || trace_flag > (int)MAX_FLAG) {
278                 LM_ERR("invalid trace flag %d\n", trace_flag);
279                 return -1;
280         }
281         trace_flag = 1 << trace_flag;
282
283         trace_to_database_flag = (int *)shm_malloc(sizeof(int));
284         if(trace_to_database_flag == NULL) {
285                 LM_ERR("no more shm memory left\n");
286                 return -1;
287         }
288
289         *trace_to_database_flag = trace_to_database;
290
291         if(hep_version != 1 && hep_version != 2 && hep_version != 3) {
292                 LM_ERR("unsupported version of HEP");
293                 return -1;
294         }
295
296         /* Find a database module if needed */
297         if(trace_to_database_flag != NULL && *trace_to_database_flag != 0) {
298                 if(db_bind_mod(&db_url, &db_funcs)) {
299                         LM_ERR("unable to bind database module\n");
300                         return -1;
301                 }
302                 if(trace_to_database_flag && !DB_CAPABILITY(db_funcs, DB_CAP_INSERT)) {
303                         LM_ERR("database modules does not provide all functions needed"
304                                    " by module\n");
305                         return -1;
306                 }
307         }
308
309         trace_on_flag = (int *)shm_malloc(sizeof(int));
310         if(trace_on_flag == NULL) {
311                 LM_ERR("no more shm memory left\n");
312                 return -1;
313         }
314
315         *trace_on_flag = trace_on;
316
317         xheaders_write_flag = (int *)shm_malloc(sizeof(int));
318         xheaders_read_flag = (int *)shm_malloc(sizeof(int));
319         if(!(xheaders_write_flag && xheaders_read_flag)) {
320                 LM_ERR("no more shm memory left\n");
321                 return -1;
322         }
323         *xheaders_write_flag = xheaders_write;
324         *xheaders_read_flag = xheaders_read;
325
326         /* register callbacks to TM */
327         if(load_tm_api(&tmb) != 0) {
328                 LM_WARN("can't load tm api. Will not install tm callbacks.\n");
329         }
330
331         if (load_dlg_api(&dlgb) < 0) {
332                 LM_WARN("can't load dlg api. Will not install dialog callbacks.\n");
333         }
334         else {
335                 if (dlgb.register_dlgcb(NULL, DLGCB_CREATED, trace_dialog, NULL, NULL) != 0) {
336                         LM_ERR("failed to register dialog callbacks! Tracing dialogs won't be available\n");
337                 }
338
339                 if(pv_parse_spec(&siptrace_info_avp_str, &avp_spec) == 0
340                                 || avp_spec.type != PVT_AVP) {
341                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
342                                         siptrace_info_avp_str.len, siptrace_info_avp_str.s);
343                         return -1;
344                 }
345
346                 if(pv_get_avp_name(
347                                    0, &avp_spec.pvp, &siptrace_info_avp, &siptrace_info_avp_type)
348                                 != 0) {
349                         LM_ERR("[%.*s] - invalid AVP definition\n", siptrace_info_avp_str.len,
350                                         siptrace_info_avp_str.s);
351                         return -1;
352                 }
353         }
354
355 #if 0
356         else if(tmb.register_tmcb(0, 0, TMCB_REQUEST_IN, trace_onreq_in, 0, 0)
357                           <= 0) {
358                 LM_ERR("can't register trace_onreq_in\n");
359                 return -1;
360         }
361 #endif
362
363         /* bind the SL API */
364         if(sl_load_api(&slb) != 0) {
365                 LM_WARN("cannot bind to SL API. Will not install sl callbacks.\n");
366         } else {
367                 /* register sl callbacks */
368                 memset(&slcb, 0, sizeof(sl_cbelem_t));
369
370                 slcb.type = SLCB_REPLY_READY;
371                 slcb.cbf = trace_sl_onreply_out;
372                 if(slb.register_cb(&slcb) != 0) {
373                         LM_ERR("can't register for SLCB_REPLY_READY\n");
374                         return -1;
375                 }
376
377                 if(trace_sl_acks) {
378                         slcb.type = SLCB_ACK_FILTERED;
379                         slcb.cbf = trace_sl_ack_in;
380                         if(slb.register_cb(&slcb) != 0) {
381                                 LM_ERR("can't register for SLCB_ACK_FILTERED\n");
382                                 return -1;
383                         }
384                 }
385         }
386
387         if(dup_uri_str.s != 0) {
388                 dup_uri = (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri));
389                 if(dup_uri == 0) {
390                         LM_ERR("no more pkg memory left\n");
391                         return -1;
392                 }
393                 memset(dup_uri, 0, sizeof(struct sip_uri));
394                 if(parse_uri(dup_uri_str.s, dup_uri_str.len, dup_uri) < 0) {
395                         LM_ERR("bad duplicate_uri\n");
396                         return -1;
397                 }
398         }
399
400         if(force_send_sock_str.s != 0) {
401                 force_send_sock_str.len = strlen(force_send_sock_str.s);
402                 force_send_sock_uri =
403                                 (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri));
404                 if(force_send_sock_uri == 0) {
405                         LM_ERR("no more pkg memory left\n");
406                         return -1;
407                 }
408                 memset(force_send_sock_uri, 0, sizeof(struct sip_uri));
409                 if(parse_uri(force_send_sock_str.s, force_send_sock_str.len,
410                                    force_send_sock_uri)
411                                 < 0) {
412                         LM_ERR("bad force_send_sock\n");
413                         return -1;
414                 }
415         }
416
417         if(traced_user_avp_str.s && traced_user_avp_str.len > 0) {
418                 if(pv_parse_spec(&traced_user_avp_str, &avp_spec) == 0
419                                 || avp_spec.type != PVT_AVP) {
420                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
421                                         traced_user_avp_str.len, traced_user_avp_str.s);
422                         return -1;
423                 }
424
425                 if(pv_get_avp_name(
426                                    0, &avp_spec.pvp, &traced_user_avp, &traced_user_avp_type)
427                                 != 0) {
428                         LM_ERR("[%.*s] - invalid AVP definition\n", traced_user_avp_str.len,
429                                         traced_user_avp_str.s);
430                         return -1;
431                 }
432         } else {
433                 traced_user_avp.n = 0;
434                 traced_user_avp_type = 0;
435         }
436         if(trace_table_avp_str.s && trace_table_avp_str.len > 0) {
437                 if(pv_parse_spec(&trace_table_avp_str, &avp_spec) == 0
438                                 || avp_spec.type != PVT_AVP) {
439                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
440                                         trace_table_avp_str.len, trace_table_avp_str.s);
441                         return -1;
442                 }
443
444                 if(pv_get_avp_name(
445                                    0, &avp_spec.pvp, &trace_table_avp, &trace_table_avp_type)
446                                 != 0) {
447                         LM_ERR("[%.*s] - invalid AVP definition\n", trace_table_avp_str.len,
448                                         trace_table_avp_str.s);
449                         return -1;
450                 }
451         } else {
452                 trace_table_avp.n = 0;
453                 trace_table_avp_type = 0;
454         }
455
456         if(_siptrace_mode == 1) {
457                 sr_event_register_cb(SREV_NET_DATA_RECV, siptrace_net_data_recv);
458                 sr_event_register_cb(SREV_NET_DATA_SEND, siptrace_net_data_send);
459         }
460         return 0;
461 }
462
463
464 static int child_init(int rank)
465 {
466         if(rank == PROC_INIT || rank == PROC_MAIN || rank == PROC_TCP_MAIN)
467                 return 0; /* do nothing for the main process */
468
469         if(trace_to_database_flag != NULL && *trace_to_database_flag != 0) {
470                 db_con = db_funcs.init(&db_url);
471                 if(!db_con) {
472                         LM_ERR("unable to connect to database. Please check "
473                                    "configuration.\n");
474                         return -1;
475                 }
476                 if(DB_CAPABILITY(db_funcs, DB_CAP_QUERY)) {
477                         if(db_check_table_version(
478                                         &db_funcs, db_con, &siptrace_table, SIP_TRACE_TABLE_VERSION)
479                                                 < 0) {
480                                 DB_TABLE_VERSION_ERROR(siptrace_table);
481                                 db_funcs.close(db_con);
482                                 db_con = 0;
483                                 return -1;
484                         }
485                 }
486         }
487
488         return 0;
489 }
490
491
492 static void destroy(void)
493 {
494         if(trace_to_database_flag != NULL && *trace_to_database_flag != 0) {
495                 if(db_con != NULL)
496                         db_funcs.close(db_con);
497         }
498
499         if(trace_on_flag)
500                 shm_free(trace_on_flag);
501 }
502
503 static inline str *siptrace_get_table(void)
504 {
505         static int_str avp_value;
506         struct usr_avp *avp;
507
508         if(trace_table_avp.n == 0)
509                 return &siptrace_table;
510
511         avp = NULL;
512         if(trace_table_avp.n != 0)
513                 avp = search_first_avp(
514                                 trace_table_avp_type, trace_table_avp, &avp_value, 0);
515
516         if(avp == NULL || !is_avp_str_val(avp) || avp_value.s.len <= 0)
517                 return &siptrace_table;
518
519         return &avp_value.s;
520 }
521
522 static int sip_trace_store(siptrace_data_t *sto, dest_info_t *dst,
523                 str *correlation_id_str)
524 {
525         if(sto == NULL) {
526                 LM_DBG("invalid parameter\n");
527                 return -1;
528         }
529
530         gettimeofday(&sto->tv, NULL);
531
532         if(sip_trace_xheaders_read(sto) != 0)
533                 return -1;
534         int ret = sip_trace_store_db(sto);
535
536         if(sip_trace_xheaders_write(sto) != 0)
537                 return -1;
538
539         if(hep_mode_on)
540                 trace_send_hep_duplicate(
541                                 &sto->body, &sto->fromip, &sto->toip, dst, correlation_id_str);
542         else
543                 trace_send_duplicate(sto->body.s, sto->body.len, dst);
544
545         if(sip_trace_xheaders_free(sto) != 0)
546                 return -1;
547
548         return ret;
549 }
550
551 static int sip_trace_store_db(siptrace_data_t *sto)
552 {
553         if(db_con == NULL) {
554                 LM_DBG("database connection not initialized\n");
555                 return -1;
556         }
557
558         if(trace_to_database_flag == NULL || *trace_to_database_flag == 0)
559                 goto done;
560
561         db_key_t db_keys[NR_KEYS];
562         db_val_t db_vals[NR_KEYS];
563
564         db_keys[0] = &msg_column;
565         db_vals[0].type = DB1_BLOB;
566         db_vals[0].nul = 0;
567         db_vals[0].val.blob_val = sto->body;
568
569         db_keys[1] = &callid_column;
570         db_vals[1].type = DB1_STR;
571         db_vals[1].nul = 0;
572         db_vals[1].val.str_val = sto->callid;
573
574         db_keys[2] = &method_column;
575         db_vals[2].type = DB1_STR;
576         db_vals[2].nul = 0;
577         db_vals[2].val.str_val = sto->method;
578
579         db_keys[3] = &status_column;
580         db_vals[3].type = DB1_STR;
581         db_vals[3].nul = 0;
582         db_vals[3].val.str_val = sto->status;
583
584         db_keys[4] = &fromip_column;
585         db_vals[4].type = DB1_STR;
586         db_vals[4].nul = 0;
587         db_vals[4].val.str_val = sto->fromip;
588
589         db_keys[5] = &toip_column;
590         db_vals[5].type = DB1_STR;
591         db_vals[5].nul = 0;
592         db_vals[5].val.str_val = sto->toip;
593
594         db_keys[6] = &date_column;
595         db_vals[6].type = DB1_DATETIME;
596         db_vals[6].nul = 0;
597         db_vals[6].val.time_val = sto->tv.tv_sec;
598
599         db_keys[7] = &direction_column;
600         db_vals[7].type = DB1_STRING;
601         db_vals[7].nul = 0;
602         db_vals[7].val.string_val = sto->dir;
603
604         db_keys[8] = &fromtag_column;
605         db_vals[8].type = DB1_STR;
606         db_vals[8].nul = 0;
607         db_vals[8].val.str_val = sto->fromtag;
608
609         db_keys[9] = &traced_user_column;
610         db_vals[9].type = DB1_STR;
611         db_vals[9].nul = 0;
612
613         db_keys[10] = &time_us_column;
614         db_vals[10].type = DB1_INT;
615         db_vals[10].nul = 0;
616         db_vals[10].val.int_val = sto->tv.tv_usec;
617
618         db_keys[11] = &totag_column;
619         db_vals[11].type = DB1_STR;
620         db_vals[11].nul = 0;
621         db_vals[11].val.str_val = sto->totag;
622
623         db_funcs.use_table(db_con, siptrace_get_table());
624
625         if(trace_on_flag != NULL && *trace_on_flag != 0) {
626                 db_vals[9].val.str_val.s = "";
627                 db_vals[9].val.str_val.len = 0;
628
629                 LM_DBG("storing info...\n");
630                 if(trace_delayed != 0 && db_funcs.insert_delayed != NULL) {
631                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
632                                 LM_ERR("error storing trace\n");
633                                 goto error;
634                         }
635                 } else {
636                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
637                                 LM_ERR("error storing trace\n");
638                                 goto error;
639                         }
640                 }
641 #ifdef STATISTICS
642                 update_stat(sto->stat, 1);
643 #endif
644         }
645
646         if(sto->avp == NULL)
647                 goto done;
648
649         db_vals[9].val.str_val = sto->avp_value.s;
650
651         LM_DBG("storing info...\n");
652         if(trace_delayed != 0 && db_funcs.insert_delayed != NULL) {
653                 if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
654                         LM_ERR("error storing trace\n");
655                         goto error;
656                 }
657         } else {
658                 if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
659                         LM_ERR("error storing trace\n");
660                         goto error;
661                 }
662         }
663
664         sto->avp = search_next_avp(&sto->state, &sto->avp_value);
665         while(sto->avp != NULL) {
666                 db_vals[9].val.str_val = sto->avp_value.s;
667
668                 LM_DBG("storing info...\n");
669                 if(trace_delayed != 0 && db_funcs.insert_delayed != NULL) {
670                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
671                                 LM_ERR("error storing trace\n");
672                                 goto error;
673                         }
674                 } else {
675                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
676                                 LM_ERR("error storing trace\n");
677                                 goto error;
678                         }
679                 }
680                 sto->avp = search_next_avp(&sto->state, &sto->avp_value);
681         }
682
683 done:
684         return 1;
685 error:
686         return -1;
687 }
688
689 enum siptrace_type_t parse_siptrace_flag(str* sflags)
690 {
691         int idx;
692         enum siptrace_type_t trace_type = SIPTRACE_NONE;
693
694         if (sflags == NULL || sflags->s == NULL || sflags->len == 0) {
695                 return SIPTRACE_NONE;
696         }
697
698         for (idx = 0; idx < sflags->len; idx++) {
699                 switch(sflags->s[idx]|0x20) { /*|0x20 - to lowercase */
700                         case SIPTRACE_MESSAGE:
701                         case SIPTRACE_TRANSACTION:
702                         case SIPTRACE_DIALOG:
703                                 if (trace_type != SIPTRACE_NONE) {
704                                         LM_ERR("only one tracing flag can be used <%.*s>!\n",
705                                                         sflags->len, sflags->s);
706                                         return SIPTRACE_NONE;
707                                 }
708
709                                 trace_type = (sflags->s[idx]|0x20);
710                                 break;
711                         case ' ':
712                         case '\t':
713                                 break;
714                         default:
715                                 LM_ERR("idx %d %d\n", idx, sflags->len);
716                                 LM_ERR("Invalid character <%c> in <%.*s>!\n", sflags->s[idx],
717                                                 sflags->len, sflags->s);
718                                 return SIPTRACE_NONE;
719                 }
720         }
721
722         return trace_type;
723 }
724
725 static int fixup_siptrace(void **param, int param_no)
726 {
727         str sflags;
728         enum siptrace_type_t trace_type;
729
730         LM_ERR("fixup function aaa\n");
731         if(param_no < 1 || param_no > 3) {
732                 LM_DBG("params:%s\n", (char *)*param);
733                 return 0;
734         }
735
736         if (param_no == 1 || param_no == 2) {
737                 /* correlation id */
738                 return fixup_spve_spve(param, param_no);
739         } else if (param_no == 3) {
740                 /* tracing type; string only */
741                 sflags.s = *param;
742                 sflags.len = strlen(*param);
743
744                 trace_type = parse_siptrace_flag(&sflags);
745                 if (trace_type == SIPTRACE_NONE) {
746                         LM_ERR("Failed to parse trace type!\n");
747                         return -1;
748                 }
749
750                 *param = pkg_malloc(sizeof(trace_type));
751                 memcpy(*param, &trace_type, sizeof(trace_type));
752         }
753
754         return 0;
755 }
756
757
758 /**
759  * TODO TODO TODO:
760  *
761  * parse_siptrace_uri (to replace siptrace_fixup and ki_sip_trace_dst_cid beginning)
762  * parse_siptrace_type
763  *
764  *
765  */
766
767 static int parse_siptrace_uri(str* duri, dest_info_t* dst)
768 {
769         sip_uri_t uri;
770         proxy_l_t *p = NULL;
771
772         if (dst == NULL) {
773                 LM_ERR("bad destination!\n");
774                 return -1;
775         }
776
777         if (duri == NULL || duri->len <= 0) {
778                 if(dup_uri) {
779                         uri = *dup_uri;
780                 } else {
781                         LM_ERR("Missing duplicate URI\n");
782                         return -1;
783                 }
784         } else {
785                 memset(&uri, 0, sizeof(struct sip_uri));
786                 if(parse_uri(duri->s, duri->len, &uri) < 0) {
787                         LM_ERR("bad dup uri\n");
788                         return -1;
789                 }
790         }
791
792         init_dest_info(dst);
793
794         /* create a temporary proxy*/
795         dst->proto = PROTO_UDP;
796         p = mk_proxy(&uri.host, (uri.port_no) ? uri.port_no : SIP_PORT, dst->proto);
797         if(p == 0) {
798                 LM_ERR("bad host name in uri\n");
799                 pkg_free(dst);
800                 return -1;
801         }
802
803         hostent2su(&dst->to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT);
804
805         /* free temporary proxy*/
806         if(p) {
807                 free_proxy(p); /* frees only p content, not p itself */
808                 pkg_free(p);
809         }
810
811         return 0;
812 }
813
814 /**
815  * Send sip trace with destination and correlation id and specify what messages to be traced
816  */
817 static int ki_sip_trace_dst_cid_flag(sip_msg_t *msg, str *duri, str *cid, str* sflag)
818 {
819         dest_info_t dst;
820         enum siptrace_type_t trace_type;
821
822         if (parse_siptrace_uri(duri, &dst) < 0) {
823                 LM_ERR("failed to parse siptrace uri!\n");
824                 return -1;
825         }
826
827         if (sflag) {
828                 trace_type = parse_siptrace_flag(sflag);
829                 if (trace_type == SIPTRACE_NONE) {
830                         LM_ERR("Invalid flags <%.*s>\n", sflag->len, sflag->s);
831                 }
832         } else {
833                 trace_type = SIPTRACE_MESSAGE;
834         }
835
836         return sip_trace(msg, &dst, cid,  NULL);
837 }
838
839 /**
840  * Send sip trace with destination and correlation id
841  */
842 static int ki_sip_trace_dst_cid(sip_msg_t *msg, str *duri, str *cid)
843 {
844         return ki_sip_trace_dst_cid_flag(msg, duri, cid, NULL);
845 }
846
847 /**
848  * Send sip trace with destination
849  */
850 static int ki_sip_trace_dst(sip_msg_t *msg, str *duri)
851 {
852         return ki_sip_trace_dst_cid_flag(msg, duri, NULL, NULL);
853 }
854
855 /**
856  *
857  */
858 static int ki_sip_trace(sip_msg_t *msg)
859 {
860         return ki_sip_trace_dst_cid_flag(msg, NULL, NULL, NULL);
861 }
862
863 /**
864  *
865  */
866 static int w_sip_trace0(sip_msg_t *msg, char *dest, char *correlation_id)
867 {
868         return w_sip_trace3(msg, NULL, NULL, NULL);
869 }
870
871 /**
872  *
873  */
874 static int w_sip_trace1(sip_msg_t *msg, char *dest)
875 {
876         return w_sip_trace3(msg, dest, NULL, NULL);
877 }
878
879 /**
880  *
881  */
882 static int w_sip_trace2(sip_msg_t *msg, char *dest, char *correlation_id)
883 {
884         return w_sip_trace3(msg, dest, correlation_id, NULL);
885 }
886
887
888 static int w_sip_trace3(sip_msg_t *msg, char *dest, char *correlation_id, char *trace_type_p)
889 {
890         avp_value_t avp_val;
891         str dup_uri_str = {0, 0};
892         str correlation_id_str = {0, 0};
893         dest_info_t dest_info;
894         enum siptrace_type_t trace_type;
895         siptrace_info_t* info;
896
897         if (dest) {
898                 if(fixup_get_svalue(msg, (gparam_t *)dest, &dup_uri_str) != 0) {
899                         LM_ERR("unable to parse the dest URI string\n");
900                         return -1;
901                 }
902         }
903
904         /* if arg dest uri is null  dup_uri_str will have length 0 and global dup_uri will be used */
905         if (parse_siptrace_uri(&dup_uri_str, &dest_info) < 0) {
906                 LM_ERR("failed to parse uri!\n");
907                 return -1;
908         }
909
910         if (correlation_id) {
911                 if(fixup_get_svalue(msg, (gparam_t *)correlation_id, &correlation_id_str)
912                                 != 0) {
913                         LM_ERR("unable to parse the correlation id\n");
914                         return -1;
915                 }
916         }
917
918         if (trace_type_p != NULL) {
919                 trace_type = *(enum siptrace_type_t *)(trace_type_p);
920         } else {
921                 /* fallback to default */
922                 trace_type = SIPTRACE_MESSAGE;
923         }
924
925         if (trace_type == SIPTRACE_TRANSACTION || trace_type == SIPTRACE_DIALOG) {
926                 /*
927                  * for each type check that conditions are created
928                  * transaction: it's a request starting a transaction; tm module loaded
929                  * dialog: it's an INVITE; dialog module is loaded
930                  *
931                  * */
932                 if (tmb.t_gett == NULL) {
933                         LM_WARN("TM module not loaded! Tracing only current message!\n");
934                         goto trace_current;
935                 }
936
937                 if (trace_type == SIPTRACE_DIALOG && dlgb.get_dlg == NULL) {
938                         LM_WARN("DIALOG module not loaded! Tracing only current message!\n");
939                         goto trace_current;
940                 }
941
942                 if (msg->first_line.type != SIP_REQUEST ||
943                                 (trace_type == SIPTRACE_DIALOG && msg->first_line.u.request.method_value != METHOD_INVITE)) {
944                         LM_WARN("When tracing a %s sip_trace() has to be initiated on the %s\n",
945                                         trace_type == SIPTRACE_TRANSACTION ? "transaction" : "dialog",
946                                         trace_type == SIPTRACE_TRANSACTION ? "request message" : "initial invite");
947                         return -1;
948                 }
949
950                 info = shm_malloc(sizeof(siptrace_info_t));
951                 if (info == NULL) {
952                         LM_ERR("No more shm!\n");
953                         return -1;
954                 }
955
956                 info->correlation_id = &correlation_id_str;
957
958                 if (trace_type == SIPTRACE_TRANSACTION) {
959                         trace_transaction(msg, info, 1);
960                 } else if (trace_type == SIPTRACE_DIALOG) {
961                         trace_transaction(msg, info, 1);
962                         if (unlikely(dlgb.set_dlg_var == NULL)) {
963                                 LM_ERR("Dialog api not loaded! will trace only current transaction!\n");
964                         } else {
965                                 /* serialize what's in info */
966                                 /* save correlation id in siptrace_info avp
967                                  * we want to have traced user avp value at the moment of sip_trace function call*/
968                                 if (serialize_siptrace_info(info, &avp_val.s) < 0) {
969                                         LM_ERR("failed to serialize siptrace info! Won't trace dialog!\n");
970                                         return -1;
971                                 } else {
972                                         /* save serialized data into an avp */
973                                         if (add_avp(siptrace_info_avp_type | AVP_VAL_STR,
974                                                                 siptrace_info_avp, avp_val) < 0) {
975                                                 LM_ERR("Failed to add <%.*s> avp value\n",
976                                                                 siptrace_info_avp_str.len, siptrace_info_avp_str.s);
977                                                 return -1;
978                                         }
979
980                                         msg->msg_flags |= FL_SIPTRACE;
981                                 }
982                         }
983                 }
984         }
985
986 trace_current:
987         return sip_trace(msg, &dest_info, &correlation_id_str, NULL);
988 }
989
990 static int sip_trace(sip_msg_t *msg, dest_info_t *dst,
991                 str *correlation_id_str, char *dir)
992 {
993         siptrace_data_t sto;
994         onsend_info_t *snd_inf = NULL;
995
996         if(msg == NULL) {
997                 LM_DBG("nothing to trace\n");
998                 return -1;
999         }
1000
1001         if(dst) {
1002                 if(dst->send_sock == 0) {
1003                         dst->send_sock = get_send_socket(0, &dst->to, dst->proto);
1004                         if(dst->send_sock == 0) {
1005                                 LM_ERR("can't forward to af %d, proto %d no corresponding"
1006                                            " listening socket\n",
1007                                                 dst->to.s.sa_family, dst->proto);
1008                                 return -1;
1009                         }
1010                 }
1011         }
1012
1013         memset(&sto, 0, sizeof(siptrace_data_t));
1014
1015         if(traced_user_avp.n != 0)
1016                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1017                                 &sto.avp_value, &sto.state);
1018
1019         if((sto.avp == NULL) && (trace_on_flag == NULL || *trace_on_flag == 0)) {
1020                 LM_DBG("trace off...\n");
1021                 return -1;
1022         }
1023
1024         if(sip_trace_prepare(msg) < 0)
1025                 return -1;
1026
1027         sto.callid = msg->callid->body;
1028
1029         if(msg->first_line.type == SIP_REQUEST) {
1030                 sto.method = msg->first_line.u.request.method;
1031         } else {
1032                 if(parse_headers(msg, HDR_CSEQ_F, 0) != 0 || msg->cseq == NULL
1033                                 || msg->cseq->parsed == NULL) {
1034                         LM_ERR("cannot parse cseq header\n");
1035                         return -1;
1036                 }
1037                 sto.method = get_cseq(msg)->method;
1038         }
1039
1040         if(msg->first_line.type == SIP_REPLY) {
1041                 sto.status = msg->first_line.u.reply.status;
1042         } else {
1043                 sto.status.s = "";
1044                 sto.status.len = 0;
1045         }
1046
1047         snd_inf = get_onsend_info();
1048         if(snd_inf == NULL) {
1049                 sto.body.s = msg->buf;
1050                 sto.body.len = msg->len;
1051
1052                 sto.dir = (dir) ? dir : "in";
1053
1054                 if(trace_local_ip.s && trace_local_ip.len > 0
1055                                 && strncmp(sto.dir, "out", 3) == 0) {
1056                         sto.fromip = trace_local_ip;
1057                 } else {
1058                         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1059                                         siptrace_proto_name(msg->rcv.proto),
1060                                         ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port);
1061                         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1062                                 LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
1063                                 sto.fromip.s = SIPTRACE_ANYADDR;
1064                                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1065                         } else {
1066                                 sto.fromip.s = sto.fromip_buff;
1067                         }
1068                 }
1069
1070                 if(trace_local_ip.s && trace_local_ip.len > 0
1071                                 && strncmp(sto.dir, "in", 2) == 0) {
1072                         sto.toip = trace_local_ip;
1073                 } else {
1074                         sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1075                                         siptrace_proto_name(msg->rcv.proto), ip_addr2a(&msg->rcv.dst_ip),
1076                                         (int)msg->rcv.dst_port);
1077                         if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1078                                 LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1079                                 sto.toip.s = SIPTRACE_ANYADDR;
1080                                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1081                         } else {
1082                                 sto.toip.s = sto.toip_buff;
1083                         }
1084                 }
1085         } else {
1086                 sto.body.s = snd_inf->buf;
1087                 sto.body.len = snd_inf->len;
1088
1089                 if(trace_local_ip.s && trace_local_ip.len > 0) {
1090                         sto.fromip = trace_local_ip;
1091                 } else {
1092                         if(snd_inf->send_sock->sock_str.len>=SIPTRACE_ADDR_MAX-1) {
1093                                 LM_WARN("local socket address is too large\n");
1094                                 sto.fromip.s = SIPTRACE_ANYADDR;
1095                                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1096                         } else {
1097                                 strncpy(sto.fromip_buff, snd_inf->send_sock->sock_str.s,
1098                                                 snd_inf->send_sock->sock_str.len);
1099                                 sto.fromip.s = sto.fromip_buff;
1100                                 sto.fromip.len = snd_inf->send_sock->sock_str.len;
1101                         }
1102                 }
1103
1104                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1105                                 siptrace_proto_name(snd_inf->send_sock->proto),
1106                                 suip2a(snd_inf->to, sizeof(*snd_inf->to)),
1107                                 (int)su_getport(snd_inf->to));
1108                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1109                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1110                         sto.toip.s = SIPTRACE_ANYADDR;
1111                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1112                 } else {
1113                         sto.toip.s = sto.toip_buff;
1114                 }
1115
1116                 sto.dir = "out";
1117         }
1118
1119         sto.fromtag = get_from(msg)->tag_value;
1120         sto.totag = get_to(msg)->tag_value;
1121
1122 #ifdef STATISTICS
1123         if(msg->first_line.type == SIP_REPLY) {
1124                 sto.stat = siptrace_rpl;
1125         } else {
1126                 sto.stat = siptrace_req;
1127         }
1128 #endif
1129         return sip_trace_store(&sto, dst, correlation_id_str);
1130 }
1131
1132 #define trace_is_off(_msg)                        \
1133          (((_msg)->msg_flags & FL_SIPTRACE) == 0)
1134
1135 static void trace_onreq_out(struct cell *t, int type, struct tmcb_params *ps)
1136 {
1137         siptrace_data_t sto;
1138         sip_msg_t *msg;
1139         ip_addr_t to_ip;
1140         dest_info_t *dst;
1141
1142         if(t == NULL || ps == NULL) {
1143                 LM_ERR("very weird\n");
1144                 return;
1145         }
1146
1147         if(ps->flags & TMCB_RETR_F) {
1148                 LM_ERR("retransmission\n");
1149                 return;
1150         }
1151         msg = ps->req;
1152         if(msg == NULL) {
1153                 /* check if it is outgoing cancel, t is INVITE
1154                  * and send_buf starts with CANCEL */
1155                 if(is_invite(t) && ps->send_buf.len > 7
1156                                 && strncmp(ps->send_buf.s, "CANCEL ", 7) == 0) {
1157                         msg = t->uas.request;
1158                         if(msg == NULL) {
1159                                 LM_DBG("no uas msg for INVITE transaction\n");
1160                                 return;
1161                         } else {
1162                                 LM_DBG("recording CANCEL based on INVITE transaction\n");
1163                         }
1164                 } else {
1165                         LM_DBG("no uas msg, local transaction\n");
1166                         return;
1167                 }
1168         }
1169         memset(&sto, 0, sizeof(siptrace_data_t));
1170
1171         if(traced_user_avp.n != 0)
1172                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1173                                 &sto.avp_value, &sto.state);
1174
1175         if((sto.avp == NULL) && trace_is_off(msg)) {
1176                 LM_DBG("trace off...\n");
1177                 return;
1178         }
1179
1180         if(sip_trace_prepare(msg) < 0)
1181                 return;
1182
1183         if(ps->send_buf.len > 0) {
1184                 sto.body = ps->send_buf;
1185         } else {
1186                 sto.body.s = "No request buffer";
1187                 sto.body.len = sizeof("No request buffer") - 1;
1188         }
1189
1190         sto.callid = msg->callid->body;
1191
1192         if(ps->send_buf.len > 10) {
1193                 sto.method.s = ps->send_buf.s;
1194                 sto.method.len = 0;
1195                 while(sto.method.len < ps->send_buf.len) {
1196                         if(ps->send_buf.s[sto.method.len] == ' ')
1197                                 break;
1198                         sto.method.len++;
1199                 }
1200                 if(sto.method.len == ps->send_buf.len)
1201                         sto.method.len = 10;
1202         } else {
1203                 sto.method = t->method;
1204         }
1205
1206         sto.status.s = "";
1207         sto.status.len = 0;
1208
1209         memset(&to_ip, 0, sizeof(struct ip_addr));
1210         dst = ps->dst;
1211
1212         if(trace_local_ip.s && trace_local_ip.len > 0) {
1213                 sto.fromip = trace_local_ip;
1214         } else {
1215                 if(dst == 0 || dst->send_sock == 0 || dst->send_sock->sock_str.s == 0) {
1216                         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1217                                         siptrace_proto_name(msg->rcv.proto),
1218                                         ip_addr2a(&msg->rcv.dst_ip), (int)msg->rcv.dst_port);
1219                         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1220                                 LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
1221                                 sto.fromip.s = SIPTRACE_ANYADDR;
1222                                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1223                         } else {
1224                                 sto.fromip.s = sto.fromip_buff;
1225                         }
1226                 } else {
1227                         sto.fromip = dst->send_sock->sock_str;
1228                 }
1229         }
1230
1231         if(dst == 0) {
1232                 sto.toip.s = SIPTRACE_ANYADDR;
1233                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1234         } else {
1235                 su2ip_addr(&to_ip, &dst->to);
1236                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1237                                 siptrace_proto_name(dst->proto),
1238                                 ip_addr2a(&to_ip), (int)su_getport(&dst->to));
1239                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1240                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1241                         sto.toip.s = SIPTRACE_ANYADDR;
1242                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1243                 } else {
1244                         sto.toip.s = sto.toip_buff;
1245                 }
1246         }
1247
1248         sto.dir = "out";
1249
1250         sto.fromtag = get_from(msg)->tag_value;
1251         sto.totag = get_to(msg)->tag_value;
1252
1253 #ifdef STATISTICS
1254         sto.stat = siptrace_req;
1255 #endif
1256
1257         sip_trace_store(&sto, NULL, NULL);
1258         return;
1259 }
1260
1261 static void trace_onreply_in(struct cell *t, int type, struct tmcb_params *ps)
1262 {
1263         siptrace_data_t sto;
1264         sip_msg_t *msg;
1265         sip_msg_t *req;
1266         char statusbuf[INT2STR_MAX_LEN];
1267
1268         if(t == NULL || t->uas.request == 0 || ps == NULL) {
1269                 LM_DBG("no uas request, local transaction\n");
1270                 return;
1271         }
1272
1273         req = ps->req;
1274         msg = ps->rpl;
1275         if((type != TMCB_ACK_NEG_IN) && (msg == NULL || req == NULL)) {
1276                 LM_DBG("no reply\n");
1277                 return;
1278         }
1279         memset(&sto, 0, sizeof(siptrace_data_t));
1280
1281         if(traced_user_avp.n != 0)
1282                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1283                                 &sto.avp_value, &sto.state);
1284
1285         if((type != TMCB_ACK_NEG_IN) && ((sto.avp == NULL) && trace_is_off(req))) {
1286                 LM_DBG("trace off... %d %d\n", sto.avp == NULL, trace_is_off(req));
1287                 return;
1288         }
1289
1290         if(sip_trace_prepare(msg) < 0)
1291                 return;
1292
1293         sto.body.s = msg->buf;
1294         sto.body.len = msg->len;
1295
1296         sto.callid = msg->callid->body;
1297
1298         sto.method = get_cseq(msg)->method;
1299
1300         sto.status.s = int2strbuf(ps->code, statusbuf, INT2STR_MAX_LEN, &sto.status.len);
1301         if(sto.status.s == 0) {
1302                 LM_ERR("failure to get the status string\n");
1303                 return;
1304         }
1305
1306         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1307                         siptrace_proto_name(msg->rcv.proto),
1308                         ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port);
1309         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1310                 LM_ERR("failed to format fromip buffer (%d)\n", sto.fromip.len);
1311                 sto.fromip.s = SIPTRACE_ANYADDR;
1312                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1313         } else {
1314                 sto.fromip.s = sto.fromip_buff;
1315         }
1316
1317         if(trace_local_ip.s && trace_local_ip.len > 0) {
1318                 sto.toip = trace_local_ip;
1319         } else {
1320                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1321                                 siptrace_proto_name(msg->rcv.proto),
1322                                 ip_addr2a(&msg->rcv.dst_ip), (int)msg->rcv.dst_port);
1323                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1324                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1325                         sto.toip.s = SIPTRACE_ANYADDR;
1326                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1327                 } else {
1328                         sto.toip.s = sto.toip_buff;
1329                 }
1330         }
1331
1332         sto.dir = "in";
1333
1334         sto.fromtag = get_from(msg)->tag_value;
1335         sto.totag = get_to(msg)->tag_value;
1336 #ifdef STATISTICS
1337         sto.stat = siptrace_rpl;
1338 #endif
1339
1340         sip_trace_store(&sto, NULL, NULL);
1341         return;
1342 }
1343
1344 static void trace_onreply_out(struct cell *t, int type, struct tmcb_params *ps)
1345 {
1346         siptrace_data_t sto;
1347         int faked = 0;
1348         struct sip_msg *msg;
1349         struct sip_msg *req;
1350         struct ip_addr to_ip;
1351         char statusbuf[INT2STR_MAX_LEN];
1352         dest_info_t *dst;
1353
1354         if(t == NULL || t->uas.request == 0 || ps == NULL) {
1355                 LM_DBG("no uas request, local transaction\n");
1356                 return;
1357         }
1358
1359         if(ps->flags & TMCB_RETR_F) {
1360                 LM_DBG("retransmission\n");
1361                 return;
1362         }
1363         memset(&sto, 0, sizeof(siptrace_data_t));
1364         if(traced_user_avp.n != 0)
1365                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1366                                 &sto.avp_value, &sto.state);
1367
1368         if((sto.avp == NULL) && trace_is_off(t->uas.request)) {
1369                 LM_DBG("trace off...\n");
1370                 return;
1371         }
1372
1373         req = ps->req;
1374         msg = ps->rpl;
1375         if(msg == NULL || msg == FAKED_REPLY) {
1376                 msg = t->uas.request;
1377                 faked = 1;
1378         }
1379
1380         if(sip_trace_prepare(msg) < 0)
1381                 return;
1382
1383         if(faked == 0) {
1384                 if(ps->send_buf.len > 0) {
1385                         sto.body = ps->send_buf;
1386                 } else if(t->uas.response.buffer != NULL) {
1387                         sto.body.s = t->uas.response.buffer;
1388                         sto.body.len = t->uas.response.buffer_len;
1389                 } else if(msg->len > 0) {
1390                         sto.body.s = msg->buf;
1391                         sto.body.len = msg->len;
1392                 } else {
1393                         sto.body.s = "No reply buffer";
1394                         sto.body.len = sizeof("No reply buffer") - 1;
1395                 }
1396         } else {
1397                 if(ps->send_buf.len > 0) {
1398                         sto.body = ps->send_buf;
1399                 } else if(t->uas.response.buffer != NULL) {
1400                         sto.body.s = t->uas.response.buffer;
1401                         sto.body.len = t->uas.response.buffer_len;
1402                 } else {
1403                         sto.body.s = "No reply buffer";
1404                         sto.body.len = sizeof("No reply buffer") - 1;
1405                 }
1406         }
1407
1408         sto.callid = msg->callid->body;
1409         sto.method = get_cseq(msg)->method;
1410
1411         if(trace_local_ip.s && trace_local_ip.len > 0) {
1412                 sto.fromip = trace_local_ip;
1413         } else {
1414                 sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1415                                 siptrace_proto_name(msg->rcv.proto),
1416                                 ip_addr2a(&req->rcv.dst_ip), (int)req->rcv.dst_port);
1417                 if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1418                         LM_ERR("failed to format fromip buffer (%d)\n", sto.fromip.len);
1419                         sto.fromip.s = SIPTRACE_ANYADDR;
1420                         sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1421                 } else {
1422                         sto.fromip.s = sto.fromip_buff;
1423                 }
1424         }
1425
1426         sto.status.s = int2strbuf(ps->code, statusbuf, INT2STR_MAX_LEN, &sto.status.len);
1427         if(sto.status.s == 0) {
1428                 LM_ERR("failure to get the status string\n");
1429                 return;
1430         }
1431
1432         memset(&to_ip, 0, sizeof(struct ip_addr));
1433         dst = ps->dst;
1434         if(dst == 0) {
1435                 sto.toip.s = SIPTRACE_ANYADDR;
1436                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1437         } else {
1438                 su2ip_addr(&to_ip, &dst->to);
1439                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1440                                 siptrace_proto_name(dst->proto),
1441                                 ip_addr2a(&to_ip), (int)su_getport(&dst->to));
1442                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1443                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1444                         sto.toip.s = SIPTRACE_ANYADDR;
1445                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1446                 } else {
1447                         sto.toip.s = sto.toip_buff;
1448                 }
1449         }
1450
1451         sto.dir = "out";
1452         sto.fromtag = get_from(msg)->tag_value;
1453         sto.totag = get_to(msg)->tag_value;
1454
1455 #ifdef STATISTICS
1456         sto.stat = siptrace_rpl;
1457 #endif
1458
1459         sip_trace_store(&sto, NULL, NULL);
1460         return;
1461 }
1462
1463 static void trace_tm_neg_ack_in(struct cell *t, int type, struct tmcb_params *ps)
1464 {
1465         LM_DBG("storing negative ack...\n");
1466
1467         /* this condition should not exist but there seems to be a BUG in kamailio
1468          * letting requests other than the ACK inside */
1469         if (ps->req->first_line.u.request.method_value != METHOD_ACK) {
1470                 return;
1471         }
1472
1473         sip_trace(ps->req, 0, NULL, NULL);
1474 }
1475
1476 static int serialize_siptrace_info(siptrace_info_t* info, str* serial_data)
1477 {
1478         if (info == NULL || info->correlation_id == NULL) {
1479                 LM_ERR("Nothing to serialize!\n");
1480                 return -1;
1481         }
1482
1483         if (serial_data == NULL) {
1484                 LM_ERR("Invalid NULL pointer for return value!\n");
1485                 return -1;
1486         }
1487
1488         serial_data->s = shm_malloc(info->correlation_id->len);
1489         if (serial_data->s == NULL) {
1490                 LM_ERR("no more shared memory!\n");
1491                 return -1;
1492         }
1493
1494         memcpy((char *)serial_data->s, info->correlation_id->s, info->correlation_id->len);
1495         serial_data->len = info->correlation_id->len;
1496
1497         return 0;
1498 }
1499
1500 static void trace_sl_ack_in(sl_cbp_t *slcbp)
1501 {
1502         sip_msg_t *req;
1503         LM_DBG("storing ack...\n");
1504         req = slcbp->req;
1505         sip_trace(req, 0, NULL, NULL);
1506 }
1507
1508 static void trace_sl_onreply_out(sl_cbp_t *slcbp)
1509 {
1510         sip_msg_t *req;
1511         siptrace_data_t sto;
1512         sip_msg_t *msg;
1513         ip_addr_t to_ip;
1514         char statusbuf[INT2STR_MAX_LEN];
1515
1516         if(slcbp == NULL || slcbp->req == NULL) {
1517                 LM_ERR("bad parameters\n");
1518                 return;
1519         }
1520         req = slcbp->req;
1521
1522         memset(&sto, 0, sizeof(siptrace_data_t));
1523         if(traced_user_avp.n != 0)
1524                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1525                                 &sto.avp_value, &sto.state);
1526
1527         if((sto.avp == NULL) && trace_is_off(req)) {
1528                 LM_DBG("trace off...\n");
1529                 return;
1530         }
1531
1532         msg = req;
1533
1534         if(sip_trace_prepare(msg) < 0)
1535                 return;
1536
1537         sto.body.s = (slcbp->reply) ? slcbp->reply->s : "";
1538         sto.body.len = (slcbp->reply) ? slcbp->reply->len : 0;
1539
1540         sto.callid = msg->callid->body;
1541         sto.method = msg->first_line.u.request.method;
1542
1543         if(trace_local_ip.len > 0) {
1544                 sto.fromip = trace_local_ip;
1545         } else {
1546                 sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1547                                 siptrace_proto_name(req->rcv.proto),
1548                                 ip_addr2a(&req->rcv.dst_ip), req->rcv.dst_port);
1549                 if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1550                         LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
1551                         sto.fromip.s = SIPTRACE_ANYADDR;
1552                         sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1553                 } else {
1554                         sto.fromip.s = sto.fromip_buff;
1555                 }
1556         }
1557
1558         sto.status.s = int2strbuf(slcbp->code, statusbuf, INT2STR_MAX_LEN, &sto.status.len);
1559         if(sto.status.s == 0) {
1560                 LM_ERR("failure to get the status string\n");
1561                 return;
1562         }
1563
1564         memset(&to_ip, 0, sizeof(struct ip_addr));
1565         if(slcbp->dst == 0) {
1566                 sto.toip.s = SIPTRACE_ANYADDR;
1567                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1568         } else {
1569                 su2ip_addr(&to_ip, &slcbp->dst->to);
1570                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1571                                 siptrace_proto_name(req->rcv.proto), ip_addr2a(&to_ip),
1572                                 (int)su_getport(&slcbp->dst->to));
1573                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1574                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1575                         sto.toip.s = SIPTRACE_ANYADDR;
1576                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1577                 } else {
1578                         sto.toip.s = sto.toip_buff;
1579                 }
1580         }
1581
1582         sto.dir = "out";
1583         sto.fromtag = get_from(msg)->tag_value;
1584         sto.totag = get_to(msg)->tag_value;
1585
1586 #ifdef STATISTICS
1587         sto.stat = siptrace_rpl;
1588 #endif
1589
1590         sip_trace_store(&sto, NULL, NULL);
1591         return;
1592 }
1593
1594 static void trace_transaction(sip_msg_t* msg, siptrace_info_t* info, int register_free_func)
1595 {
1596         /* trace current message on out */
1597         msg->msg_flags |= FL_SIPTRACE;
1598
1599         LM_ERR("trace request out registration\n");
1600         if(tmb.register_tmcb(msg, 0, TMCB_REQUEST_SENT, trace_onreq_out, info, 0) <= 0) {
1601                 LM_ERR("can't register trace_onreq_out\n");
1602                 return;
1603         }
1604
1605         /* trace reply on in */
1606         if(tmb.register_tmcb(msg, 0, TMCB_RESPONSE_IN, trace_onreply_in, info, 0) <= 0) {
1607                 LM_ERR("can't register trace_onreply_in\n");
1608                 return;
1609         }
1610
1611         /* trace reply on out */
1612         LM_CRIT("trace resp sent!\n");
1613         if(tmb.register_tmcb(msg, 0, TMCB_RESPONSE_SENT, trace_onreply_out, info, register_free_func ? free_trace_info : 0)
1614                         <= 0) {
1615                 LM_ERR("can't register trace_onreply_out\n");
1616                 return;
1617         }
1618
1619         /* TODO */
1620         /* check the following callbacks: TMCB_REQUEST_PENDING, TMCB_RESPONSE_READY, TMCB_ACK_NEG_IN */
1621         /* trace reply on in */
1622         if(tmb.register_tmcb(msg, 0, TMCB_ACK_NEG_IN, trace_tm_neg_ack_in, info, 0) <= 0) {
1623                 LM_ERR("can't register trace_onreply_in\n");
1624                 return;
1625         }
1626 }
1627
1628 //static void trace_dialog(sip_msg_t* msg, siptrace_info_t* info)
1629 static void trace_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params *params)
1630 {
1631         int_str avp_value;
1632         struct usr_avp* avp = NULL;
1633
1634         LM_ERR("TRACING THIS DIALOGHES!\n");
1635
1636         if (!dlgb.get_dlg) {
1637                 LM_ERR("Dialog API not loaded! Trace off...\n");
1638                 return;
1639         }
1640
1641         /* request - params->req */
1642         if (params == NULL || params->req == NULL) {
1643                 LM_ERR("Invalid args!\n");
1644                 return;
1645         }
1646
1647         if (!(params->req->msg_flags & FL_SIPTRACE)) {
1648                 LM_DBG("Trace is off for this request...\n");
1649                 return;
1650         }
1651
1652         avp = search_first_avp(siptrace_info_avp_type, siptrace_info_avp, &avp_value, 0);
1653         if (avp == NULL) {
1654                 LM_ERR("Siptrace info avp not set!\n");
1655                 return;
1656         }
1657
1658         if (dlgb.set_dlg_var(dlg,
1659                                 &siptrace_info_dlgkey,
1660                                 &avp_value.s) != 0) {
1661                 LM_ERR("failed to set siptrace info dlgkey\n");
1662                 return;
1663         }
1664
1665         if(dlgb.register_dlgcb(dlg, DLGCB_REQ_WITHIN,
1666                                 trace_dialog_transaction, 0, 0) != 0) {
1667                 LM_ERR("Failed to register DLGCB_TERMINATED callback!\n");
1668                 return;
1669         }
1670
1671         if(dlgb.register_dlgcb(dlg, DLGCB_TERMINATED,
1672                                 trace_dialog_transaction, 0, 0) != 0) {
1673                 LM_ERR("Failed to register DLGCB_TERMINATED callback!\n");
1674                 return;
1675         }
1676
1677         /* flag for stateless replies?? */
1678
1679         /* trace negative ACKS? */
1680         /* trace 180? */
1681         /* trace CANCEL and BYE transactions */
1682         return;
1683 }
1684
1685
1686 static void trace_dialog_transaction(struct dlg_cell* dlg, int type, struct dlg_cb_params *params)
1687 {
1688         siptrace_info_t info;
1689
1690         memset(&info, 0, sizeof(siptrace_info_t));
1691         info.correlation_id = dlgb.get_dlg_var(dlg, &siptrace_info_dlgkey);
1692
1693         /**
1694          * DUAL BYE - internally generated BYE from kamailio
1695          * set flag to signal request_in callback which will register
1696          * transaction callbacks to catch caller and callee BYEs and their
1697          * responses
1698          */
1699         if (params->req == NULL && params->rpl == NULL) {
1700                 LM_DBG("dual bye!\n");
1701                 return;
1702         }
1703
1704         trace_transaction(params->req, &info, 0);
1705
1706         sip_trace(params->req, NULL, info.correlation_id, NULL);
1707 }
1708
1709 static void free_trace_info(void* trace_info)
1710 {
1711         LM_DBG("free trace info!\n");
1712         if (!trace_info) return;
1713
1714         shm_free(trace_info);
1715 }
1716
1717 /**
1718  *
1719  */
1720 int siptrace_net_data_recv(sr_event_param_t *evp)
1721 {
1722         sr_net_info_t *nd;
1723         siptrace_data_t sto;
1724
1725         if(evp->data == 0)
1726                 return -1;
1727
1728         nd = (sr_net_info_t *)evp->data;
1729         if(nd->rcv == NULL || nd->data.s == NULL || nd->data.len <= 0)
1730                 return -1;
1731
1732         memset(&sto, 0, sizeof(siptrace_data_t));
1733
1734         sto.body.s = nd->data.s;
1735         sto.body.len = nd->data.len;
1736
1737         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1738                         siptrace_proto_name(nd->rcv->proto),
1739                         ip_addr2a(&nd->rcv->src_ip), (int)nd->rcv->src_port);
1740         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1741                 LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
1742                 sto.fromip.s = SIPTRACE_ANYADDR;
1743                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1744         } else {
1745                 sto.fromip.s = sto.fromip_buff;
1746         }
1747
1748         sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1749                         siptrace_proto_name(nd->rcv->proto), ip_addr2a(&nd->rcv->dst_ip),
1750                         (int)nd->rcv->dst_port);
1751         if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1752                 LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1753                 sto.toip.s = SIPTRACE_ANYADDR;
1754                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1755         } else {
1756                 sto.toip.s = sto.toip_buff;
1757         }
1758
1759         sto.dir = "in";
1760
1761         trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL, NULL);
1762         return 0;
1763 }
1764
1765 /**
1766  *
1767  */
1768 int siptrace_net_data_send(sr_event_param_t *evp)
1769 {
1770         sr_net_info_t *nd;
1771         dest_info_t new_dst;
1772         siptrace_data_t sto;
1773
1774         if(evp->data == 0)
1775                 return -1;
1776
1777         nd = (sr_net_info_t *)evp->data;
1778         if(nd->dst == NULL || nd->data.s == NULL || nd->data.len <= 0)
1779                 return -1;
1780
1781         new_dst = *nd->dst;
1782
1783         if(new_dst.send_sock == 0) {
1784                 new_dst.send_sock = get_send_socket(0, &nd->dst->to, nd->dst->proto);
1785         }
1786
1787         memset(&sto, 0, sizeof(siptrace_data_t));
1788
1789         sto.body.s = nd->data.s;
1790         sto.body.len = nd->data.len;
1791
1792         if(unlikely(new_dst.send_sock == 0)) {
1793                 LM_WARN("no sending socket found\n");
1794                 strcpy(sto.fromip_buff, SIPTRACE_ANYADDR);
1795                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1796         } else {
1797                 if(new_dst.send_sock->sock_str.len>=SIPTRACE_ADDR_MAX-1) {
1798                         LM_ERR("socket string is too large: %d\n",
1799                                         new_dst.send_sock->sock_str.len);
1800                         goto error;
1801                 }
1802                 strncpy(sto.fromip_buff, new_dst.send_sock->sock_str.s,
1803                                 new_dst.send_sock->sock_str.len);
1804                 sto.fromip.len = new_dst.send_sock->sock_str.len;
1805         }
1806         sto.fromip.s = sto.fromip_buff;
1807
1808         sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1809                         siptrace_proto_name(new_dst.send_sock->proto),
1810                         suip2a(&new_dst.to, sizeof(new_dst.to)),
1811                         (int)su_getport(&new_dst.to));
1812         if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1813                 LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1814                 sto.toip.s = SIPTRACE_ANYADDR;
1815                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1816         } else {
1817                 sto.toip.s = sto.toip_buff;
1818         }
1819
1820         sto.dir = "out";
1821
1822         trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL, NULL);
1823         return 0;
1824
1825 error:
1826         return -1;
1827 }
1828
1829 /**
1830  *
1831  */
1832 static int w_hlog1(struct sip_msg *msg, char *message, char *_)
1833 {
1834         str smessage;
1835         if(fixup_get_svalue(msg, (gparam_t *)message, &smessage) != 0) {
1836                 LM_ERR("unable to parse the message\n");
1837                 return -1;
1838         }
1839         return hlog(msg, NULL, &smessage);
1840 }
1841
1842 /**
1843  *
1844  */
1845 static int ki_hlog(sip_msg_t *msg, str *message)
1846 {
1847         return hlog(msg, NULL, message);
1848 }
1849
1850 /**
1851  *
1852  */
1853 static int w_hlog2(struct sip_msg *msg, char *correlationid, char *message)
1854 {
1855         str scorrelationid, smessage;
1856         if(fixup_get_svalue(msg, (gparam_t *)correlationid, &scorrelationid) != 0) {
1857                 LM_ERR("unable to parse the correlation id\n");
1858                 return -1;
1859         }
1860         if(fixup_get_svalue(msg, (gparam_t *)message, &smessage) != 0) {
1861                 LM_ERR("unable to parse the message\n");
1862                 return -1;
1863         }
1864         return hlog(msg, &scorrelationid, &smessage);
1865 }
1866
1867 /**
1868  *
1869  */
1870 static int ki_hlog_cid(sip_msg_t *msg, str *correlationid, str *message)
1871 {
1872         return hlog(msg, correlationid, message);
1873 }
1874
1875 /**
1876  *
1877  */
1878 static void siptrace_rpc_status(rpc_t *rpc, void *c)
1879 {
1880         str status = {0, 0};
1881
1882         if(rpc->scan(c, "S", &status) < 1) {
1883                 rpc->fault(c, 500, "Not enough parameters (on, off or check)");
1884                 return;
1885         }
1886
1887         if(trace_on_flag == NULL) {
1888                 rpc->fault(c, 500, "Internal error");
1889                 return;
1890         }
1891
1892         if(strncasecmp(status.s, "on", strlen("on")) == 0) {
1893                 *trace_on_flag = 1;
1894                 rpc->rpl_printf(c, "Enabled");
1895                 return;
1896         }
1897         if(strncasecmp(status.s, "off", strlen("off")) == 0) {
1898                 *trace_on_flag = 0;
1899                 rpc->rpl_printf(c, "Disabled");
1900                 return;
1901         }
1902         if(strncasecmp(status.s, "check", strlen("check")) == 0) {
1903                 rpc->rpl_printf(c, *trace_on_flag ? "Enabled" : "Disabled");
1904                 return;
1905         }
1906         rpc->fault(c, 500, "Bad parameter (on, off or check)");
1907         return;
1908 }
1909
1910 static const char *siptrace_status_doc[2] = {
1911         "Get status or turn on/off siptrace. Parameters: on, off or check.",
1912         0
1913 };
1914
1915 rpc_export_t siptrace_rpc[] = {
1916         {"siptrace.status", siptrace_rpc_status, siptrace_status_doc, 0},
1917         {0, 0, 0, 0}
1918 };
1919
1920 static int siptrace_init_rpc(void)
1921 {
1922         if(rpc_register_array(siptrace_rpc) != 0) {
1923                 LM_ERR("failed to register RPC commands\n");
1924                 return -1;
1925         }
1926         return 0;
1927 }
1928
1929 /**
1930  *
1931  */
1932 /* clang-format off */
1933 static sr_kemi_t sr_kemi_siptrace_exports[] = {
1934         { str_init("siptrace"), str_init("sip_trace"),
1935                 SR_KEMIP_INT, ki_sip_trace,
1936                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1937                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1938         },
1939         { str_init("siptrace"), str_init("sip_trace_dst"),
1940                 SR_KEMIP_INT, ki_sip_trace_dst,
1941                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1942                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1943         },
1944         { str_init("siptrace"), str_init("sip_trace_dst_cid"),
1945                 SR_KEMIP_INT, ki_sip_trace_dst_cid,
1946                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
1947                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1948         },
1949         { str_init("siptrace"), str_init("sip_trace_dst_cid_type"),
1950                 SR_KEMIP_INT, ki_sip_trace_dst_cid_flag,
1951                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
1952                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1953         },
1954         { str_init("siptrace"), str_init("hlog"),
1955                 SR_KEMIP_INT, ki_hlog,
1956                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1957                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1958         },
1959         { str_init("siptrace"), str_init("hlog_cid"),
1960                 SR_KEMIP_INT, ki_hlog_cid,
1961                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
1962                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1963         },
1964
1965         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
1966 };
1967 /* clang-format on */
1968
1969 /**
1970  *
1971  */
1972 int mod_register(char *path, int *dlflags, void *p1, void *p2)
1973 {
1974         sr_kemi_modules_add(sr_kemi_siptrace_exports);
1975         return 0;
1976 }