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