siptrace: trace_mode can be used to automatically store traffic to db or mirror via...
[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_MODE_NONE 0
64 #define SIPTRACE_MODE_HEP (1)
65 #define SIPTRACE_MODE_DB  (1<<1)
66 #define SIPTRACE_MODE_URI (1<<2)
67
68 #define SIPTRACE_ANYADDR "any:255.255.255.255:5060"
69 #define SIPTRACE_ANYADDR_LEN (sizeof(SIPTRACE_ANYADDR) - 1)
70
71 #define trace_is_off(_msg)                        \
72          (((_msg)->msg_flags & FL_SIPTRACE) == 0) 
73
74 #define is_null_pv(_str) \
75         (!str_strcmp(&_str, pv_get_null_str()))
76
77 struct tm_binds tmb;
78 struct dlg_binds dlgb;
79
80 /** SL API structure */
81 sl_api_t slb;
82
83 /* module function prototypes */
84 static int mod_init(void);
85 static int siptrace_init_rpc(void);
86 static int child_init(int rank);
87 static void destroy(void);
88 static int sip_trace(sip_msg_t *msg, dest_info_t *, str *, char *);
89 static int w_sip_trace0(struct sip_msg *, char *p1, char *p2);
90 static int w_sip_trace1(struct sip_msg *, char *dest, char *p2);
91 static int w_sip_trace2(struct sip_msg *, char *dest, char *correlation_id);
92 static int w_sip_trace3(struct sip_msg *, char *dest, char *correlation_id, char *trace_type);
93 static int fixup_siptrace(void **param, int param_no);
94 static int w_sip_trace_mode(sip_msg_t *msg, char *pmode, char *p2);
95
96 static int parse_siptrace_uri(str* duri, dest_info_t* dst);
97 static enum siptrace_type_t parse_siptrace_flag(str* sflags);
98
99 static int w_hlog1(struct sip_msg *, char *message, char *);
100 static int w_hlog2(struct sip_msg *, char *correlationid, char *message);
101
102 static int sip_trace_store_db(siptrace_data_t *sto);
103
104 static void trace_onreq_out(struct cell *t, int type, struct tmcb_params *ps);
105 static void trace_cancel_in(struct cell *t, int type, struct tmcb_params *ps);
106 static void trace_onreply_in(struct cell *t, int type, struct tmcb_params *ps);
107 static void trace_onreply_out(struct cell *t, int type, struct tmcb_params *ps);
108 static void trace_tm_neg_ack_in(struct cell *t, int type, struct tmcb_params *ps);
109 static void trace_sl_onreply_out(sl_cbp_t *slcb);
110 static void trace_sl_ack_in(sl_cbp_t *slcb);
111
112
113
114 static void trace_transaction(sip_msg_t* msg, siptrace_info_t* info, int dlg_tran);
115 static void trace_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params *params);
116 static void trace_dialog_transaction(struct dlg_cell* dlg, int type, struct dlg_cb_params *params);
117 static void free_trace_info(void* trace_info);
118 static int  add_info_xavp(siptrace_info_t* info);
119 static inline int parse_raw_uri(siptrace_info_t* info);
120
121 int siptrace_net_data_recv(sr_event_param_t *evp);
122 int siptrace_net_data_send(sr_event_param_t *evp);
123 static int _siptrace_mode = 0;
124
125
126 static str db_url = str_init(DEFAULT_DB_URL);
127 static str siptrace_table = str_init("sip_trace");
128 static str date_column = str_init("time_stamp");                 /* 00 */
129 static str callid_column = str_init("callid");                   /* 01 */
130 static str traced_user_column = str_init("traced_user"); /* 02 */
131 static str msg_column = str_init("msg");                                 /* 03 */
132 static str method_column = str_init("method");                   /* 04 */
133 static str status_column = str_init("status");                   /* 05 */
134 static str fromip_column = str_init("fromip");                   /* 06 */
135 static str toip_column = str_init("toip");                               /* 07 */
136 static str fromtag_column = str_init("fromtag");                 /* 08 */
137 static str direction_column = str_init("direction");     /* 09 */
138 static str time_us_column = str_init("time_us");                 /* 10 */
139 static str totag_column = str_init("totag");                     /* 11 */
140
141 #define XAVP_TRACE_INFO_NAME "trace_info"
142 static str xavp_trace_info_name_s = str_init(XAVP_TRACE_INFO_NAME);
143
144 #define NR_KEYS 12
145 #define SIP_TRACE_TABLE_VERSION 4
146
147 int trace_flag_param = -1;
148 int trace_flag = 0;
149
150 int trace_on = 0;
151 int trace_sl_acks = 1;
152
153 int trace_to_database = 1;
154 int trace_delayed = 0;
155
156 int hep_version = 1;
157 int hep_capture_id = 1;
158 int hep_vendor_id = 0;
159 str auth_key_str = {0, 0};
160
161 int xheaders_write = 0;
162 int xheaders_read = 0;
163
164 str force_send_sock_str = {0, 0};
165 struct sip_uri *force_send_sock_uri = 0;
166
167 str dup_uri_str = {0, 0};
168 struct sip_uri *dup_uri = 0;
169
170 int *trace_on_flag = NULL;
171 int *trace_to_database_flag = NULL;
172
173 int *xheaders_write_flag = NULL;
174 int *xheaders_read_flag = NULL;
175
176 static unsigned short traced_user_avp_type = 0;
177 static int_str traced_user_avp;
178 static str traced_user_avp_str = {NULL, 0};
179
180 static unsigned short trace_table_avp_type = 0;
181 static int_str trace_table_avp;
182 static str trace_table_avp_str = {NULL, 0};
183
184 static str trace_local_ip = {NULL, 0};
185
186 int hep_mode_on = 0;
187
188 db1_con_t *db_con = NULL; /*!< database connection */
189 db_func_t db_funcs;               /*!< Database functions */
190
191 /*! \brief
192  * Exported functions
193  */
194 static cmd_export_t cmds[] = {
195         {"sip_trace", (cmd_function)w_sip_trace0, 0, 0, 0,
196                 ANY_ROUTE},
197         {"sip_trace", (cmd_function)w_sip_trace1, 1, fixup_siptrace, 0,
198                 ANY_ROUTE},
199         {"sip_trace", (cmd_function)w_sip_trace2, 2, fixup_siptrace, 0,
200                 ANY_ROUTE},
201         {"sip_trace", (cmd_function)w_sip_trace3, 3, fixup_siptrace, 0,
202                 ANY_ROUTE},
203         {"hlog", (cmd_function)w_hlog1, 1, fixup_spve_null, 0,
204                 ANY_ROUTE},
205         {"hlog", (cmd_function)w_hlog2, 2, fixup_spve_spve, 0,
206                 ANY_ROUTE},
207         {"sip_trace_mode", (cmd_function)w_sip_trace_mode, 1, fixup_spve_null,
208                 fixup_free_spve_null, ANY_ROUTE},
209         {0, 0, 0, 0, 0, 0}
210 };
211
212
213 /*! \brief
214  * Exported parameters
215  */
216 static param_export_t params[] = {
217         {"auth_key", PARAM_STR, &auth_key_str},
218         {"db_url", PARAM_STR, &db_url},
219         {"table", PARAM_STR, &siptrace_table},
220         {"date_column", PARAM_STR, &date_column},
221         {"callid_column", PARAM_STR, &callid_column},
222         {"traced_user_column", PARAM_STR, &traced_user_column},
223         {"msg_column", PARAM_STR, &msg_column},
224         {"method_column", PARAM_STR, &method_column},
225         {"status_column", PARAM_STR, &status_column},
226         {"fromip_column", PARAM_STR, &fromip_column},
227         {"toip_column", PARAM_STR, &toip_column},
228         {"fromtag_column", PARAM_STR, &fromtag_column},
229         {"totag_column", PARAM_STR, &totag_column},
230         {"direction_column", PARAM_STR, &direction_column},
231         {"trace_flag", INT_PARAM, &trace_flag_param},
232         {"trace_on", INT_PARAM, &trace_on},
233         {"traced_user_avp", PARAM_STR, &traced_user_avp_str},
234         {"trace_table_avp", PARAM_STR, &trace_table_avp_str},
235         {"duplicate_uri", PARAM_STR, &dup_uri_str},
236         {"trace_to_database", INT_PARAM, &trace_to_database},
237         {"trace_local_ip", PARAM_STR, &trace_local_ip},
238         {"trace_sl_acks", INT_PARAM, &trace_sl_acks},
239         {"xheaders_write", INT_PARAM, &xheaders_write},
240         {"xheaders_read", INT_PARAM, &xheaders_read},
241         {"hep_mode_on", INT_PARAM, &hep_mode_on},
242         {"force_send_sock", PARAM_STR, &force_send_sock_str},
243         {"hep_version", INT_PARAM, &hep_version},
244         {"hep_capture_id", INT_PARAM, &hep_capture_id},
245         {"trace_delayed", INT_PARAM, &trace_delayed},
246         {"trace_mode", PARAM_INT, &_siptrace_mode}, {0, 0, 0}
247 };
248
249 #ifdef STATISTICS
250 stat_var *siptrace_req;
251 stat_var *siptrace_rpl;
252
253 stat_export_t siptrace_stats[] = {
254         {"traced_requests", 0, &siptrace_req},
255         {"traced_replies", 0, &siptrace_rpl}, {0, 0, 0}
256 };
257 #endif
258
259 /*! \brief module exports */
260 struct module_exports exports = {
261         "siptrace",     /*!< module name */
262         DEFAULT_DLFLAGS, /*!< dlopen flags */
263         cmds,                   /*!< exported functions */
264         params,                 /*!< exported parameters */
265         0,                              /*!< exported rpc functions */
266         0,                              /*!< exported pseudo-variables */
267         0,                              /*!< response function */
268         mod_init,               /*!< module initialization function */
269         child_init,             /*!< child initialization function */
270         destroy                 /*!< destroy function */
271 };
272
273
274 /*! \brief Initialize siptrace module */
275 static int mod_init(void)
276 {
277         pv_spec_t avp_spec;
278         sl_cbelem_t slcb;
279
280 #ifdef STATISTICS
281         /* register statistics */
282         if(register_module_stats(exports.name, siptrace_stats) != 0) {
283                 LM_ERR("failed to register core statistics\n");
284                 return -1;
285         }
286 #endif
287
288         if(siptrace_init_rpc() != 0) {
289                 LM_ERR("failed to register RPC commands\n");
290                 return -1;
291         }
292
293         if(trace_flag_param!=-1) {
294                 if(trace_flag_param < -1 || trace_flag_param > (int)MAX_FLAG) {
295                         LM_ERR("invalid trace flag %d\n", trace_flag_param);
296                         return -1;
297                 }
298                 trace_flag = 1 << trace_flag_param;
299         }
300
301         trace_to_database_flag = (int *)shm_malloc(sizeof(int));
302         if(trace_to_database_flag == NULL) {
303                 LM_ERR("no more shm memory left\n");
304                 return -1;
305         }
306
307         *trace_to_database_flag = trace_to_database;
308
309         if(hep_version != 1 && hep_version != 2 && hep_version != 3) {
310                 LM_ERR("unsupported version of HEP");
311                 return -1;
312         }
313
314         /* Find a database module if needed */
315         if((_siptrace_mode & SIPTRACE_MODE_DB)
316                         || (trace_to_database_flag != NULL && *trace_to_database_flag != 0)) {
317                 if(db_bind_mod(&db_url, &db_funcs)) {
318                         LM_ERR("unable to bind database module\n");
319                         return -1;
320                 }
321                 if(trace_to_database_flag && !DB_CAPABILITY(db_funcs, DB_CAP_INSERT)) {
322                         LM_ERR("database modules does not provide all functions needed"
323                                    " by module\n");
324                         return -1;
325                 }
326         }
327
328         trace_on_flag = (int *)shm_malloc(sizeof(int));
329         if(trace_on_flag == NULL) {
330                 LM_ERR("no more shm memory left\n");
331                 return -1;
332         }
333
334         *trace_on_flag = trace_on;
335
336         xheaders_write_flag = (int *)shm_malloc(sizeof(int));
337         xheaders_read_flag = (int *)shm_malloc(sizeof(int));
338         if(!(xheaders_write_flag && xheaders_read_flag)) {
339                 LM_ERR("no more shm memory left\n");
340                 return -1;
341         }
342         *xheaders_write_flag = xheaders_write;
343         *xheaders_read_flag = xheaders_read;
344
345         /* register callbacks to TM */
346         if(load_tm_api(&tmb) != 0) {
347                 LM_WARN("can't load tm api. Will not install tm callbacks.\n");
348         }
349
350         if (load_dlg_api(&dlgb) < 0) {
351                 LM_INFO("can't load dlg api. Will not install dialog callbacks.\n");
352         } else {
353                 if (dlgb.register_dlgcb(NULL, DLGCB_CREATED, trace_dialog, NULL, NULL) != 0) {
354                         LM_ERR("failed to register dialog callbacks! Tracing dialogs won't be available\n");
355                 }
356         }
357
358         /* bind the SL API */
359         if(sl_load_api(&slb) != 0) {
360                 LM_WARN("cannot bind to SL API. Will not install sl callbacks.\n");
361         } else {
362                 /* register sl callbacks */
363                 memset(&slcb, 0, sizeof(sl_cbelem_t));
364
365                 slcb.type = SLCB_REPLY_READY;
366                 slcb.cbf = trace_sl_onreply_out;
367                 if(slb.register_cb(&slcb) != 0) {
368                         LM_ERR("can't register for SLCB_REPLY_READY\n");
369                         return -1;
370                 }
371
372                 if(trace_sl_acks) {
373                         slcb.type = SLCB_ACK_FILTERED;
374                         slcb.cbf = trace_sl_ack_in;
375                         if(slb.register_cb(&slcb) != 0) {
376                                 LM_ERR("can't register for SLCB_ACK_FILTERED\n");
377                                 return -1;
378                         }
379                 }
380         }
381
382         if(dup_uri_str.s != 0) {
383                 dup_uri = (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri));
384                 if(dup_uri == 0) {
385                         LM_ERR("no more pkg memory left\n");
386                         return -1;
387                 }
388                 memset(dup_uri, 0, sizeof(struct sip_uri));
389                 if(parse_uri(dup_uri_str.s, dup_uri_str.len, dup_uri) < 0) {
390                         LM_ERR("bad duplicate_uri\n");
391                         return -1;
392                 }
393                 if(!dup_uri->proto) {
394                         dup_uri->proto = PROTO_UDP;
395                 }
396                 if(!dup_uri->port_no) {
397                         dup_uri->port_no = SIP_PORT;
398                 }
399         }
400
401         if(force_send_sock_str.s != 0) {
402                 force_send_sock_str.len = strlen(force_send_sock_str.s);
403                 force_send_sock_uri =
404                                 (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri));
405                 if(force_send_sock_uri == 0) {
406                         LM_ERR("no more pkg memory left\n");
407                         return -1;
408                 }
409                 memset(force_send_sock_uri, 0, sizeof(struct sip_uri));
410                 if(parse_uri(force_send_sock_str.s, force_send_sock_str.len,
411                                    force_send_sock_uri)
412                                 < 0) {
413                         LM_ERR("bad force_send_sock\n");
414                         return -1;
415                 }
416                 if(!force_send_sock_uri->proto) {
417                         force_send_sock_uri->proto = PROTO_UDP;
418                 }
419                 if(!force_send_sock_uri->port_no) {
420                         force_send_sock_uri->port_no = SIP_PORT;
421                 }
422         }
423
424         if(traced_user_avp_str.s && traced_user_avp_str.len > 0) {
425                 if(pv_parse_spec(&traced_user_avp_str, &avp_spec) == 0
426                                 || avp_spec.type != PVT_AVP) {
427                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
428                                         traced_user_avp_str.len, traced_user_avp_str.s);
429                         return -1;
430                 }
431
432                 if(pv_get_avp_name(
433                                    0, &avp_spec.pvp, &traced_user_avp, &traced_user_avp_type)
434                                 != 0) {
435                         LM_ERR("[%.*s] - invalid AVP definition\n", traced_user_avp_str.len,
436                                         traced_user_avp_str.s);
437                         return -1;
438                 }
439         } else {
440                 traced_user_avp.n = 0;
441                 traced_user_avp_type = 0;
442         }
443         if(trace_table_avp_str.s && trace_table_avp_str.len > 0) {
444                 if(pv_parse_spec(&trace_table_avp_str, &avp_spec) == 0
445                                 || avp_spec.type != PVT_AVP) {
446                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
447                                         trace_table_avp_str.len, trace_table_avp_str.s);
448                         return -1;
449                 }
450
451                 if(pv_get_avp_name(
452                                    0, &avp_spec.pvp, &trace_table_avp, &trace_table_avp_type)
453                                 != 0) {
454                         LM_ERR("[%.*s] - invalid AVP definition\n", trace_table_avp_str.len,
455                                         trace_table_avp_str.s);
456                         return -1;
457                 }
458         } else {
459                 trace_table_avp.n = 0;
460                 trace_table_avp_type = 0;
461         }
462
463         if(_siptrace_mode != SIPTRACE_MODE_NONE) {
464                 sr_event_register_cb(SREV_NET_DATA_RECV, siptrace_net_data_recv);
465                 sr_event_register_cb(SREV_NET_DATA_SEND, siptrace_net_data_send);
466         }
467         return 0;
468 }
469
470
471 static int child_init(int rank)
472 {
473         if(rank == PROC_INIT || rank == PROC_MAIN || rank == PROC_TCP_MAIN)
474                 return 0; /* do nothing for the main process */
475
476         if((_siptrace_mode & SIPTRACE_MODE_DB)
477                         || (trace_to_database_flag != NULL && *trace_to_database_flag != 0)) {
478                 db_con = db_funcs.init(&db_url);
479                 if(!db_con) {
480                         LM_ERR("unable to connect to database. Please check "
481                                    "configuration.\n");
482                         return -1;
483                 }
484                 if(DB_CAPABILITY(db_funcs, DB_CAP_QUERY)) {
485                         if(db_check_table_version(
486                                         &db_funcs, db_con, &siptrace_table, SIP_TRACE_TABLE_VERSION)
487                                                 < 0) {
488                                 DB_TABLE_VERSION_ERROR(siptrace_table);
489                                 db_funcs.close(db_con);
490                                 db_con = 0;
491                                 return -1;
492                         }
493                 }
494         }
495
496         return 0;
497 }
498
499
500 static void destroy(void)
501 {
502         if(trace_to_database_flag != NULL) {
503                 if(db_con != NULL) {
504                         db_funcs.close(db_con);
505                 }
506                 shm_free(trace_to_database_flag);
507         }
508
509         if(trace_on_flag) {
510                 shm_free(trace_on_flag);
511         }
512 }
513
514 static inline str *siptrace_get_table(void)
515 {
516         static int_str avp_value;
517         struct usr_avp *avp;
518
519         if(trace_table_avp.n == 0)
520                 return &siptrace_table;
521
522         avp = NULL;
523         if(trace_table_avp.n != 0)
524                 avp = search_first_avp(
525                                 trace_table_avp_type, trace_table_avp, &avp_value, 0);
526
527         if(avp == NULL || !is_avp_str_val(avp) || avp_value.s.len <= 0)
528                 return &siptrace_table;
529
530         return &avp_value.s;
531 }
532
533 static int sip_trace_store(siptrace_data_t *sto, dest_info_t *dst,
534                 str *correlation_id_str)
535 {
536         int ret = 1;
537
538         if(sto == NULL) {
539                 LM_DBG("invalid parameter\n");
540                 return -1;
541         }
542
543         gettimeofday(&sto->tv, NULL);
544
545         if(sip_trace_xheaders_read(sto) != 0)
546                 return -1;
547
548         ret = sip_trace_store_db(sto);
549
550         if(sip_trace_xheaders_write(sto) != 0)
551                 return -1;
552
553         if(hep_mode_on) {
554                 trace_send_hep_duplicate(
555                                 &sto->body, &sto->fromip, &sto->toip, dst, correlation_id_str);
556         } else {
557                 if(dst) {
558                         trace_send_duplicate(sto->body.s, sto->body.len, dst);
559                 }
560         }
561
562         if(sip_trace_xheaders_free(sto) != 0)
563                 return -1;
564
565         return ret;
566 }
567
568 static int sip_trace_store_db(siptrace_data_t *sto)
569 {
570         if(trace_to_database_flag == NULL || *trace_to_database_flag == 0)
571                 goto done;
572
573         if(db_con == NULL) {
574                 LM_DBG("database connection not initialized\n");
575                 return -1;
576         }
577
578         db_key_t db_keys[NR_KEYS];
579         db_val_t db_vals[NR_KEYS];
580
581         db_keys[0] = &msg_column;
582         db_vals[0].type = DB1_BLOB;
583         db_vals[0].nul = 0;
584         db_vals[0].val.blob_val = sto->body;
585
586         db_keys[1] = &callid_column;
587         db_vals[1].type = DB1_STR;
588         db_vals[1].nul = 0;
589         db_vals[1].val.str_val = sto->callid;
590
591         db_keys[2] = &method_column;
592         db_vals[2].type = DB1_STR;
593         db_vals[2].nul = 0;
594         db_vals[2].val.str_val = sto->method;
595
596         db_keys[3] = &status_column;
597         db_vals[3].type = DB1_STR;
598         db_vals[3].nul = 0;
599         db_vals[3].val.str_val = sto->status;
600
601         db_keys[4] = &fromip_column;
602         db_vals[4].type = DB1_STR;
603         db_vals[4].nul = 0;
604         db_vals[4].val.str_val = sto->fromip;
605
606         db_keys[5] = &toip_column;
607         db_vals[5].type = DB1_STR;
608         db_vals[5].nul = 0;
609         db_vals[5].val.str_val = sto->toip;
610
611         db_keys[6] = &date_column;
612         db_vals[6].type = DB1_DATETIME;
613         db_vals[6].nul = 0;
614         db_vals[6].val.time_val = sto->tv.tv_sec;
615
616         db_keys[7] = &direction_column;
617         db_vals[7].type = DB1_STRING;
618         db_vals[7].nul = 0;
619         db_vals[7].val.string_val = sto->dir;
620
621         db_keys[8] = &fromtag_column;
622         db_vals[8].type = DB1_STR;
623         db_vals[8].nul = 0;
624         db_vals[8].val.str_val = sto->fromtag;
625
626         db_keys[9] = &traced_user_column;
627         db_vals[9].type = DB1_STR;
628         db_vals[9].nul = 0;
629
630         db_keys[10] = &time_us_column;
631         db_vals[10].type = DB1_INT;
632         db_vals[10].nul = 0;
633         db_vals[10].val.int_val = sto->tv.tv_usec;
634
635         db_keys[11] = &totag_column;
636         db_vals[11].type = DB1_STR;
637         db_vals[11].nul = 0;
638         db_vals[11].val.str_val = sto->totag;
639
640         db_funcs.use_table(db_con, siptrace_get_table());
641
642         if(trace_on_flag != NULL && *trace_on_flag != 0) {
643                 db_vals[9].val.str_val.s = "";
644                 db_vals[9].val.str_val.len = 0;
645
646                 LM_DBG("storing info...\n");
647                 if(trace_delayed != 0 && db_funcs.insert_delayed != NULL) {
648                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
649                                 LM_ERR("error storing trace\n");
650                                 goto error;
651                         }
652                 } else {
653                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
654                                 LM_ERR("error storing trace\n");
655                                 goto error;
656                         }
657                 }
658 #ifdef STATISTICS
659                 update_stat(sto->stat, 1);
660 #endif
661         }
662
663         if(sto->avp == NULL)
664                 goto done;
665
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
681         sto->avp = search_next_avp(&sto->state, &sto->avp_value);
682         while(sto->avp != NULL) {
683                 db_vals[9].val.str_val = sto->avp_value.s;
684
685                 LM_DBG("storing info...\n");
686                 if(trace_delayed != 0 && db_funcs.insert_delayed != NULL) {
687                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
688                                 LM_ERR("error storing trace\n");
689                                 goto error;
690                         }
691                 } else {
692                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
693                                 LM_ERR("error storing trace\n");
694                                 goto error;
695                         }
696                 }
697                 sto->avp = search_next_avp(&sto->state, &sto->avp_value);
698         }
699
700 done:
701         return 1;
702 error:
703         return -1;
704 }
705
706 enum siptrace_type_t parse_siptrace_flag(str* sflags)
707 {
708         int idx;
709         enum siptrace_type_t trace_type = SIPTRACE_NONE;
710
711         if (sflags == NULL || sflags->s == NULL || sflags->len == 0) {
712                 return SIPTRACE_NONE;
713         }
714
715         for (idx = 0; idx < sflags->len; idx++) {
716                 switch(sflags->s[idx]|0x20) { /*|0x20 - to lowercase */
717                         case SIPTRACE_MESSAGE:
718                         case SIPTRACE_TRANSACTION:
719                         case SIPTRACE_DIALOG:
720                                 if (trace_type != SIPTRACE_NONE) {
721                                         LM_ERR("only one tracing flag can be used <%.*s>!\n",
722                                                         sflags->len, sflags->s);
723                                         return SIPTRACE_NONE;
724                                 }
725
726                                 trace_type = (sflags->s[idx]|0x20);
727                                 break;
728                         case ' ':
729                         case '\t':
730                                 break;
731                         default:
732                                 LM_ERR("Invalid character <%c> in <%.*s> at position <%d>!\n", sflags->s[idx],
733                                                 sflags->len, sflags->s, idx);
734                                 return SIPTRACE_NONE;
735                 }
736         }
737
738         return trace_type;
739 }
740
741 static int fixup_siptrace(void **param, int param_no)
742 {
743         str sflags;
744         enum siptrace_type_t trace_type;
745
746         if(param_no < 1 || param_no > 3) {
747                 LM_DBG("params:%s\n", (char *)*param);
748                 return 0;
749         }
750
751         if (param_no == 1 || param_no == 2) {
752                 /* correlation id */
753                 return fixup_spve_all(param, param_no);
754         } else if (param_no == 3) {
755                 /* tracing type; string only */
756                 sflags.s = (char *)*param;
757                 sflags.len = strlen(sflags.s);
758
759                 trace_type = parse_siptrace_flag(&sflags);
760                 if (trace_type == SIPTRACE_NONE) {
761                         LM_ERR("Failed to parse trace type!\n");
762                         return -1;
763                 }
764
765                 *param = pkg_malloc(sizeof(trace_type));
766                 if (*param == NULL) {
767                         LM_ERR("no more pkg memory!\n");
768                         return -1;
769                 }
770                 memcpy(*param, &trace_type, sizeof(trace_type));
771         }
772
773         return 0;
774 }
775
776
777 /**
778  *
779  * parse_siptrace_uri (to replace siptrace_fixup and ki_sip_trace_dst_cid beginning)
780  * parse_siptrace_type
781  *
782  */
783
784 static int parse_siptrace_uri(str* duri, dest_info_t* dst)
785 {
786         sip_uri_t uri;
787         proxy_l_t *p = NULL;
788
789         if (dst == NULL) {
790                 LM_ERR("bad destination!\n");
791                 return -1;
792         }
793
794         if (duri == NULL || duri->len <= 0) {
795                 if(dup_uri) {
796                         uri = *dup_uri;
797                 } else {
798                         LM_ERR("Missing duplicate URI\n");
799                         return -1;
800                 }
801         } else {
802                 memset(&uri, 0, sizeof(struct sip_uri));
803                 if(parse_uri(duri->s, duri->len, &uri) < 0) {
804                         LM_ERR("bad dup uri\n");
805                         return -1;
806                 }
807                 if(!uri.proto) {
808                         uri.proto = PROTO_UDP;
809                 }
810                 if(!uri.port_no) {
811                         uri.port_no = SIP_PORT;
812                 }
813         }
814
815         init_dest_info(dst);
816
817         /* create a temporary proxy*/
818         dst->proto = uri.proto;
819         p = mk_proxy(&uri.host, uri.port_no, dst->proto);
820         if(p == 0) {
821                 LM_ERR("bad host name in uri\n");
822                 return -1;
823         }
824
825         hostent2su(&dst->to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT);
826
827         /* free temporary proxy*/
828         if(p) {
829                 free_proxy(p); /* frees only p content, not p itself */
830                 pkg_free(p);
831         }
832
833         return 0;
834 }
835
836 /**
837  *
838  */
839 static int sip_trace_helper(sip_msg_t *msg, dest_info_t *dst, str *duri,
840                 str *corid, char *dir, enum siptrace_type_t trace_type)
841 {
842         siptrace_info_t* info = NULL;
843         struct cell *t_invite, *orig_t;
844         char *p = NULL;
845         int canceled;
846         int ret = 0;
847
848         if (trace_type == SIPTRACE_TRANSACTION || trace_type == SIPTRACE_DIALOG) {
849                 int alloc_size = sizeof(siptrace_info_t);
850
851                 /*
852                  * for each type check that conditions are created
853                  * transaction: it's a request starting a transaction; tm module loaded
854                  * dialog: it's an INVITE; dialog module is loaded
855                  *
856                  * */
857                 if (tmb.t_gett == NULL) {
858                         LM_WARN("TM module not loaded! Tracing only current message!\n");
859                         goto trace_current;
860                 }
861
862     /* if sip_trace is called over an incoming CANCEL, skip
863      * capturing it if the cancelled transaction is already being traced
864      */
865                 if (msg->REQ_METHOD==METHOD_CANCEL) {
866                         t_invite=tmb.t_lookup_original(msg);
867                         if (t_invite!=T_NULL_CELL) {
868                                 if (t_invite->uas.request->msg_flags & FL_SIPTRACE) {
869                                         LM_DBG("Transaction is already been traced, skipping.\n");
870                                         tmb.t_unref(msg);
871                                         return 1;
872                                 }
873                                 tmb.t_unref(msg);
874                         }
875                 }
876           
877                 /* if sip_trace is called over an incoming ACK, skip
878                  * capturing it if it's an ACK for a negative reply for
879                  * an already traced transaction
880                  */
881                 if (msg->REQ_METHOD==METHOD_ACK) {
882                         orig_t = tmb.t_gett();
883                         if(tmb.t_lookup_request(msg,0,&canceled)) {
884                                 t_invite = tmb.t_gett();
885                                 if (t_invite->uas.request->msg_flags & FL_SIPTRACE) {
886                                         LM_DBG("Transaction is already been traced, skipping.\n");
887                                         ret = 1;
888                                 }
889                                 tmb.t_release_transaction( t_invite );
890                                 tmb.t_unref(msg);
891                                 tmb.t_sett(orig_t, T_BR_UNDEFINED);
892                                 if (ret)
893                                         return 1;
894                         }
895                 }
896
897                 if (trace_type == SIPTRACE_DIALOG && dlgb.get_dlg == NULL) {
898                         LM_WARN("DIALOG module not loaded! Tracing only current message!\n");
899                         goto trace_current;
900                 }
901
902                 if (msg->first_line.type != SIP_REQUEST ||
903                                 (trace_type == SIPTRACE_DIALOG && msg->first_line.u.request.method_value != METHOD_INVITE)) {
904                         LM_WARN("When tracing a %s sip_trace() has to be initiated on the %s\n",
905                                         trace_type == SIPTRACE_TRANSACTION ? "transaction" : "dialog",
906                                         trace_type == SIPTRACE_TRANSACTION ? "request message" : "initial invite");
907                         return -1;
908                 }
909
910                 if (corid) {
911                         alloc_size += corid->len;
912                 }
913
914                 if (duri) {
915                         alloc_size += duri->len;
916                 }
917
918                 info = shm_malloc(alloc_size);
919                 if (info == NULL) {
920                         LM_ERR("No more shm!\n");
921                         return -1;
922                 }
923                 memset(info, 0, alloc_size);
924
925                 p = (char *)(info + 1);
926                 /* could use the dest_info we've already parsed but there's no way to pass
927                  * it to DLGCB_CREATED callback so the only thing to do is keep
928                  * it as uri, serialize in a dlg_var and parse again in DLGCB_CREATED */
929                 if(corid) {
930                         info->correlation_id.s = p;
931                         info->correlation_id.len = corid->len;
932                         memcpy(info->correlation_id.s, corid->s, corid->len);
933                 }
934                 if (duri) {
935                         info->uriState = STRACE_RAW_URI;
936                         info->u.dup_uri.s = p + ((info->correlation_id.s)?info->correlation_id.len:0);
937                         memcpy(info->u.dup_uri.s, duri->s, duri->len);
938                         info->u.dup_uri.len = duri->len;
939                 } else {
940                         info->uriState = STRACE_UNUSED_URI;
941                 }
942
943                 if (trace_type == SIPTRACE_TRANSACTION) {
944                         trace_transaction(msg, info, 0);
945                 } else if (trace_type == SIPTRACE_DIALOG) {
946                         if (unlikely(dlgb.set_dlg_var == NULL)) {
947                                 /* FIXME should we abort tracing here? */
948                                 LM_WARN("Dialog api not loaded! will trace only current transaction!\n");
949                         } else {
950                                 /* serialize what's in info */
951                                 /* save correlation id in siptrace_info avp
952                                  * we want to have traced user avp value at the moment of sip_trace function call*/
953                                 if (add_info_xavp(info) < 0) {
954                                         LM_ERR("failed to serialize siptrace info! Won't trace dialog!\n");
955                                         return -1;
956                                 } else {
957                                         msg->msg_flags |= FL_SIPTRACE;
958                                 }
959                         }
960
961                         /**
962                          * WARNING: don't move trace_transaction before  add_info_xavp()
963                          * add_info_xavp() expects the URI in RAW format, unparsed
964                          * trace_transaction() parses the URI if it finds it in raw format;
965                          * a BUG will be thrown if this happens
966                          */
967                         trace_transaction(msg, info, 1);
968                 }
969         }
970
971         if(trace_type != SIPTRACE_MESSAGE && trace_is_off(msg)) {
972                 LM_DBG("trace off...\n");
973                 return 1;
974         }
975
976 trace_current:
977         return sip_trace(msg, dst, corid, dir);
978 }
979
980 /**
981  * Send sip trace with destination and correlation id and specify what messages to be traced
982  */
983 static int ki_sip_trace_dst_cid_flag(sip_msg_t *msg, str *duri, str *cid, str* sflag)
984 {
985         dest_info_t dst;
986         enum siptrace_type_t trace_type;
987
988         if(duri) {
989                 if (parse_siptrace_uri(duri, &dst) < 0) {
990                         LM_ERR("failed to parse siptrace uri!\n");
991                         return -1;
992                 }
993         }
994
995         if (sflag) {
996                 trace_type = parse_siptrace_flag(sflag);
997                 if (trace_type == SIPTRACE_NONE) {
998                         LM_ERR("Invalid flags <%.*s>\n", sflag->len, sflag->s);
999                 }
1000         } else {
1001                 trace_type = SIPTRACE_MESSAGE;
1002         }
1003
1004         return sip_trace_helper(msg, (duri)?&dst:NULL, duri, cid, NULL, trace_type);
1005 }
1006
1007 /**
1008  * Send sip trace with destination and correlation id
1009  */
1010 static int ki_sip_trace_dst_cid(sip_msg_t *msg, str *duri, str *cid)
1011 {
1012         return ki_sip_trace_dst_cid_flag(msg, duri, cid, NULL);
1013 }
1014
1015 /**
1016  * Send sip trace with destination
1017  */
1018 static int ki_sip_trace_dst(sip_msg_t *msg, str *duri)
1019 {
1020         return ki_sip_trace_dst_cid_flag(msg, duri, NULL, NULL);
1021 }
1022
1023 /**
1024  *
1025  */
1026 static int ki_sip_trace(sip_msg_t *msg)
1027 {
1028         return ki_sip_trace_dst_cid_flag(msg, NULL, NULL, NULL);
1029 }
1030
1031 /**
1032  *
1033  */
1034 static int w_sip_trace0(sip_msg_t *msg, char *dest, char *correlation_id)
1035 {
1036         return w_sip_trace3(msg, NULL, NULL, NULL);
1037 }
1038
1039 /**
1040  *
1041  */
1042 static int w_sip_trace1(sip_msg_t *msg, char *dest, char *p2)
1043 {
1044         return w_sip_trace3(msg, dest, NULL, NULL);
1045 }
1046
1047 /**
1048  *
1049  */
1050 static int w_sip_trace2(sip_msg_t *msg, char *dest, char *correlation_id)
1051 {
1052         return w_sip_trace3(msg, dest, correlation_id, NULL);
1053 }
1054
1055
1056 static int w_sip_trace3(sip_msg_t *msg, char *dest, char *correlation_id, char *trace_type_p)
1057 {
1058         str dup_uri_param_str = {0, 0};
1059         str correlation_id_str = {0, 0};
1060         dest_info_t dest_info;
1061         enum siptrace_type_t trace_type;
1062
1063         if (dest) {
1064                 if(fixup_get_svalue(msg, (gparam_t *)dest, &dup_uri_param_str) != 0) {
1065                         LM_ERR("unable to parse the dest URI string\n");
1066                         return -1;
1067                 }
1068
1069                 if (dup_uri_param_str.s == 0 || (is_null_pv(dup_uri_param_str))) {
1070                         if (dup_uri_str.s == 0 || dup_uri_str.len == 0) {
1071                                 LM_ERR("no duplicate_uri modparam nor duplicate uri sip_trace() argument provided!\n");
1072                                 return -1;
1073                         }
1074
1075                         dup_uri_param_str = dup_uri_str;
1076                 }
1077
1078                 /* if arg dest uri is null  dup_uri_param_str will have length 0 and global dup_uri will be used */
1079                 if (parse_siptrace_uri(&dup_uri_param_str, &dest_info) < 0) {
1080                         LM_ERR("failed to parse uri!\n");
1081                         return -1;
1082                 }
1083         } else {
1084                 memset(&dest_info, 0, sizeof(dest_info_t));
1085         }
1086
1087         if (correlation_id) {
1088                 if(fixup_get_svalue(msg, (gparam_t *)correlation_id, &correlation_id_str)
1089                                 != 0) {
1090                         LM_ERR("unable to parse the correlation id\n");
1091                         return -1;
1092                 }
1093         }
1094
1095         if (trace_type_p != NULL) {
1096                 trace_type = *(enum siptrace_type_t *)(trace_type_p);
1097         } else {
1098                 /* fallback to default - transaction tracking when flag is set,
1099                  * otherwise only the current message*/
1100                 if(msg->flags & trace_flag) {
1101                         trace_type = SIPTRACE_TRANSACTION;
1102                 } else {
1103                         trace_type = SIPTRACE_MESSAGE;
1104                 }
1105         }
1106
1107         return sip_trace_helper(msg, (dest)?&dest_info:NULL,
1108                         (dest)?&dup_uri_param_str:NULL,
1109                         (correlation_id)?&correlation_id_str:NULL, NULL, trace_type);
1110 }
1111
1112 static int sip_trace(sip_msg_t *msg, dest_info_t *dst,
1113                 str *correlation_id_str, char *dir)
1114 {
1115         siptrace_data_t sto;
1116         onsend_info_t *snd_inf = NULL;
1117
1118         if(msg == NULL) {
1119                 LM_DBG("nothing to trace\n");
1120                 return -1;
1121         }
1122
1123         if(dst) {
1124                 if(dst->send_sock == 0) {
1125                         dst->send_sock = get_send_socket(0, &dst->to, dst->proto);
1126                         if(dst->send_sock == 0) {
1127                                 LM_ERR("can't forward to af %d, proto %d no corresponding"
1128                                            " listening socket\n",
1129                                                 dst->to.s.sa_family, dst->proto);
1130                                 return -1;
1131                         }
1132                 }
1133         }
1134
1135         memset(&sto, 0, sizeof(siptrace_data_t));
1136
1137         if(traced_user_avp.n != 0)
1138                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1139                                 &sto.avp_value, &sto.state);
1140
1141         if((sto.avp == NULL) && (trace_on_flag == NULL || *trace_on_flag == 0)) {
1142                 LM_DBG("trace off...\n");
1143                 return -1;
1144         }
1145
1146         if(sip_trace_prepare(msg) < 0)
1147                 return -1;
1148
1149         sto.callid = msg->callid->body;
1150
1151         if(msg->first_line.type == SIP_REQUEST) {
1152                 sto.method = msg->first_line.u.request.method;
1153         } else {
1154                 if(parse_headers(msg, HDR_CSEQ_F, 0) != 0 || msg->cseq == NULL
1155                                 || msg->cseq->parsed == NULL) {
1156                         LM_ERR("cannot parse cseq header\n");
1157                         return -1;
1158                 }
1159                 sto.method = get_cseq(msg)->method;
1160         }
1161
1162         if(msg->first_line.type == SIP_REPLY) {
1163                 sto.status = msg->first_line.u.reply.status;
1164         } else {
1165                 sto.status.s = "";
1166                 sto.status.len = 0;
1167         }
1168
1169         snd_inf = get_onsend_info();
1170         if(snd_inf == NULL) {
1171                 sto.body.s = msg->buf;
1172                 sto.body.len = msg->len;
1173
1174                 sto.dir = (dir) ? dir : "in";
1175
1176                 if(trace_local_ip.s && trace_local_ip.len > 0
1177                                 && strncmp(sto.dir, "out", 3) == 0) {
1178                         sto.fromip = trace_local_ip;
1179                 } else {
1180                         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1181                                         siptrace_proto_name(msg->rcv.proto),
1182                                         ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port);
1183                         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1184                                 LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
1185                                 sto.fromip.s = SIPTRACE_ANYADDR;
1186                                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1187                         } else {
1188                                 sto.fromip.s = sto.fromip_buff;
1189                         }
1190                 }
1191
1192                 if(trace_local_ip.s && trace_local_ip.len > 0
1193                                 && strncmp(sto.dir, "in", 2) == 0) {
1194                         sto.toip = trace_local_ip;
1195                 } else {
1196                         sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1197                                         siptrace_proto_name(msg->rcv.proto), ip_addr2a(&msg->rcv.dst_ip),
1198                                         (int)msg->rcv.dst_port);
1199                         if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1200                                 LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1201                                 sto.toip.s = SIPTRACE_ANYADDR;
1202                                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1203                         } else {
1204                                 sto.toip.s = sto.toip_buff;
1205                         }
1206                 }
1207         } else {
1208                 sto.body.s = snd_inf->buf;
1209                 sto.body.len = snd_inf->len;
1210
1211                 if(trace_local_ip.s && trace_local_ip.len > 0) {
1212                         sto.fromip = trace_local_ip;
1213                 } else {
1214                         if(snd_inf->send_sock->sock_str.len>=SIPTRACE_ADDR_MAX-1) {
1215                                 LM_WARN("local socket address is too large\n");
1216                                 sto.fromip.s = SIPTRACE_ANYADDR;
1217                                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1218                         } else {
1219                                 strncpy(sto.fromip_buff, snd_inf->send_sock->sock_str.s,
1220                                                 snd_inf->send_sock->sock_str.len);
1221                                 sto.fromip.s = sto.fromip_buff;
1222                                 sto.fromip.len = snd_inf->send_sock->sock_str.len;
1223                         }
1224                 }
1225
1226                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1227                                 siptrace_proto_name(snd_inf->send_sock->proto),
1228                                 suip2a(snd_inf->to, sizeof(*snd_inf->to)),
1229                                 (int)su_getport(snd_inf->to));
1230                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1231                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1232                         sto.toip.s = SIPTRACE_ANYADDR;
1233                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1234                 } else {
1235                         sto.toip.s = sto.toip_buff;
1236                 }
1237
1238                 sto.dir = "out";
1239         }
1240
1241         sto.fromtag = get_from(msg)->tag_value;
1242         sto.totag = get_to(msg)->tag_value;
1243
1244 #ifdef STATISTICS
1245         if(msg->first_line.type == SIP_REPLY) {
1246                 sto.stat = siptrace_rpl;
1247         } else {
1248                 sto.stat = siptrace_req;
1249         }
1250 #endif
1251         return sip_trace_store(&sto, dst, correlation_id_str);
1252 }
1253
1254
1255 /**
1256  *
1257  */
1258 static int ki_sip_trace_mode(sip_msg_t *msg, str *smode)
1259 {
1260         enum siptrace_type_t trace_type;
1261
1262         if(smode==NULL || smode->s==NULL || smode->len<=0) {
1263                 LM_INFO("no tracing mode - trace message\n");
1264                 trace_type = SIPTRACE_MESSAGE;
1265         } else {
1266                 switch(smode->s[0]) {
1267                         case 'M':
1268                         case 'm':
1269                                 trace_type = SIPTRACE_MESSAGE;
1270                         break;
1271                         case 'T':
1272                         case 't':
1273                                 trace_type = SIPTRACE_TRANSACTION;
1274                         break;
1275                         case 'D':
1276                         case 'd':
1277                                 trace_type = SIPTRACE_DIALOG;
1278                         break;
1279                         default:
1280                                 trace_type = SIPTRACE_MESSAGE;
1281                                 LM_INFO("unexpected tracing mode [%.*s] - trace message\n",
1282                                                 smode->len, smode->s);
1283                 }
1284         }
1285
1286         return sip_trace_helper(msg, NULL, NULL, NULL, NULL, trace_type);
1287 }
1288
1289 /**
1290  *
1291  */
1292 static int w_sip_trace_mode(sip_msg_t *msg, char *pmode, char *p2)
1293 {
1294         str smode = STR_NULL;
1295         if(fixup_get_svalue(msg, (gparam_t*)pmode, &smode)<0) {
1296                 LM_ERR("failed to get tracing mode parameter\n");
1297                 return -1;
1298         }
1299         return ki_sip_trace_mode(msg, &smode);
1300 }
1301
1302 static void trace_cancel_in(struct cell *t, int type, struct tmcb_params *ps)
1303 {
1304         siptrace_info_t* info;
1305         sip_msg_t *msg;
1306
1307         if(t == NULL || ps == NULL) {
1308                 LM_ERR("unexpected parameter values\n");
1309                 return;
1310         }
1311
1312         if(ps->flags & TMCB_RETR_F) {
1313                 LM_DBG("retransmission - ignoring\n");
1314                 return;
1315         }
1316
1317         info = (siptrace_info_t *)(*ps->param);
1318         msg = ps->req;
1319         if(tmb.register_tmcb(msg, 0, TMCB_RESPONSE_READY, trace_onreply_out, info, 0) <= 0) {
1320                 LM_ERR("can't register trace_onreply_out\n");
1321                 return;
1322         }
1323         msg->msg_flags |= FL_SIPTRACE;
1324         sip_trace_helper(msg, NULL, NULL, NULL, NULL, 1);
1325 }
1326
1327 static void trace_onreq_out(struct cell *t, int type, struct tmcb_params *ps)
1328 {
1329         siptrace_data_t sto;
1330         siptrace_info_t* info;
1331         sip_msg_t *msg;
1332         ip_addr_t to_ip;
1333         dest_info_t *dst;
1334
1335         if(t == NULL || ps == NULL) {
1336                 LM_ERR("unexpected parameter values\n");
1337                 return;
1338         }
1339
1340         if(ps->flags & TMCB_RETR_F) {
1341                 LM_DBG("retransmission - ignoring\n");
1342                 return;
1343         }
1344         info = (siptrace_info_t *)(*ps->param);
1345
1346         msg = ps->req;
1347         if(msg == NULL) {
1348                 /* check if it is outgoing cancel, t is INVITE
1349                  * and send_buf starts with CANCEL */
1350                 if(is_invite(t) && ps->send_buf.len > 7
1351                                 && strncmp(ps->send_buf.s, "CANCEL ", 7) == 0) {
1352                         msg = t->uas.request;
1353                         if(msg == NULL) {
1354                                 LM_DBG("no uas msg for INVITE transaction\n");
1355                                 return;
1356                         } else {
1357                                 LM_DBG("recording CANCEL based on INVITE transaction\n");
1358                         }
1359                 } else {
1360                         LM_DBG("no uas msg, local transaction\n");
1361                         return;
1362                 }
1363         }
1364
1365         /* for incoming cancel this is the only play(i've found) where I have the CANCEL transaction
1366          * and can register a callback for the reply */
1367         memset(&sto, 0, sizeof(siptrace_data_t));
1368
1369         if(traced_user_avp.n != 0)
1370                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1371                                 &sto.avp_value, &sto.state);
1372
1373         if((sto.avp == NULL) && trace_is_off(msg)) {
1374                 LM_DBG("trace off...\n");
1375                 return;
1376         }
1377
1378         if(sip_trace_prepare(msg) < 0)
1379                 return;
1380
1381         if(ps->send_buf.len > 0) {
1382                 sto.body = ps->send_buf;
1383         } else {
1384                 sto.body.s = "No request buffer";
1385                 sto.body.len = sizeof("No request buffer") - 1;
1386         }
1387
1388         sto.callid = msg->callid->body;
1389
1390         if(ps->send_buf.len > 10) {
1391                 sto.method.s = ps->send_buf.s;
1392                 sto.method.len = 0;
1393                 while(sto.method.len < ps->send_buf.len) {
1394                         if(ps->send_buf.s[sto.method.len] == ' ')
1395                                 break;
1396                         sto.method.len++;
1397                 }
1398                 if(sto.method.len == ps->send_buf.len)
1399                         sto.method.len = 10;
1400         } else {
1401                 sto.method = t->method;
1402         }
1403
1404         sto.status.s = "";
1405         sto.status.len = 0;
1406
1407         memset(&to_ip, 0, sizeof(struct ip_addr));
1408         /* destination info from the original message
1409          * used to fetch information to set the from and to for this message
1410          * different from the dest_info in siptrace_info which is the socket
1411          * used to send the message */
1412         dst = ps->dst;
1413
1414         if(trace_local_ip.s && trace_local_ip.len > 0) {
1415                 sto.fromip = trace_local_ip;
1416         } else {
1417                 if(dst == 0 || dst->send_sock == 0 || dst->send_sock->sock_str.s == 0) {
1418                         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1419                                         siptrace_proto_name(msg->rcv.proto),
1420                                         ip_addr2a(&msg->rcv.dst_ip), (int)msg->rcv.dst_port);
1421                         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1422                                 LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
1423                                 sto.fromip.s = SIPTRACE_ANYADDR;
1424                                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1425                         } else {
1426                                 sto.fromip.s = sto.fromip_buff;
1427                         }
1428                 } else {
1429                         sto.fromip = dst->send_sock->sock_str;
1430                 }
1431         }
1432
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         /* FIXME the callback is designed for outgoing requests but this along with
1451          * the callback registration at the begining of the function it's for a special
1452          * case - incoming CANCEL transactions; they were not traced before; TMCB_E2ECANCEL_IN
1453          * will throw the incoming request through this function and the callback in the beginning
1454          * will make sure the reply for this cancel is caught */
1455         if (unlikely(type == TMCB_E2ECANCEL_IN)) {
1456                 sto.dir = "in";
1457         } else {
1458                 sto.dir = "out";
1459         }
1460
1461         sto.fromtag = get_from(msg)->tag_value;
1462         sto.totag = get_to(msg)->tag_value;
1463
1464 #ifdef STATISTICS
1465         sto.stat = siptrace_req;
1466 #endif
1467
1468         if (info->uriState == STRACE_RAW_URI) {
1469                 LM_BUG("uriState must be either UNUSED or PARSED here! must be a bug! Message won't be traced!\n");
1470                 return;
1471         }
1472
1473         sip_trace_store(&sto, info->uriState == STRACE_PARSED_URI ? &info->u.dest_info : NULL, NULL);
1474         return;
1475 }
1476
1477 static void trace_onreply_in(struct cell *t, int type, struct tmcb_params *ps)
1478 {
1479         siptrace_data_t sto;
1480         siptrace_info_t* info;
1481         sip_msg_t *msg;
1482         sip_msg_t *req;
1483         char statusbuf[INT2STR_MAX_LEN];
1484
1485         if(t == NULL || t->uas.request == 0 || ps == NULL) {
1486                 LM_DBG("no uas request, local transaction\n");
1487                 return;
1488         }
1489
1490         req = ps->req;
1491         msg = ps->rpl;
1492         if((type != TMCB_ACK_NEG_IN) && (msg == NULL || req == NULL)) {
1493                 LM_DBG("no reply\n");
1494                 return;
1495         }
1496         info = (siptrace_info_t *)(*ps->param);
1497
1498         memset(&sto, 0, sizeof(siptrace_data_t));
1499
1500         if(traced_user_avp.n != 0)
1501                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1502                                 &sto.avp_value, &sto.state);
1503
1504         if((type != TMCB_ACK_NEG_IN) && ((sto.avp == NULL) && trace_is_off(req))) {
1505                 LM_DBG("trace off... %d %d\n", sto.avp == NULL, trace_is_off(req));
1506                 return;
1507         }
1508
1509         if(sip_trace_prepare(msg) < 0)
1510                 return;
1511
1512         sto.body.s = msg->buf;
1513         sto.body.len = msg->len;
1514
1515         sto.callid = msg->callid->body;
1516
1517         sto.method = get_cseq(msg)->method;
1518
1519         sto.status.s = int2strbuf(ps->code, statusbuf, INT2STR_MAX_LEN, &sto.status.len);
1520         if(sto.status.s == 0) {
1521                 LM_ERR("failure to get the status string\n");
1522                 return;
1523         }
1524
1525         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1526                         siptrace_proto_name(msg->rcv.proto),
1527                         ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port);
1528         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1529                 LM_ERR("failed to format fromip buffer (%d)\n", sto.fromip.len);
1530                 sto.fromip.s = SIPTRACE_ANYADDR;
1531                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1532         } else {
1533                 sto.fromip.s = sto.fromip_buff;
1534         }
1535
1536         if(trace_local_ip.s && trace_local_ip.len > 0) {
1537                 sto.toip = trace_local_ip;
1538         } else {
1539                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1540                                 siptrace_proto_name(msg->rcv.proto),
1541                                 ip_addr2a(&msg->rcv.dst_ip), (int)msg->rcv.dst_port);
1542                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1543                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1544                         sto.toip.s = SIPTRACE_ANYADDR;
1545                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1546                 } else {
1547                         sto.toip.s = sto.toip_buff;
1548                 }
1549         }
1550
1551         sto.dir = "in";
1552
1553         sto.fromtag = get_from(msg)->tag_value;
1554         sto.totag = get_to(msg)->tag_value;
1555 #ifdef STATISTICS
1556         sto.stat = siptrace_rpl;
1557 #endif
1558
1559         if (info->uriState == STRACE_RAW_URI) {
1560                 LM_BUG("uriState must be either UNUSED or PARSED here! must be a bug! Message won't be traced!\n");
1561                 return;
1562         }
1563
1564         sip_trace_store(&sto, info->uriState == STRACE_PARSED_URI ? &info->u.dest_info : NULL, NULL);
1565         return;
1566 }
1567
1568 static void trace_onreply_out(struct cell *t, int type, struct tmcb_params *ps)
1569 {
1570         siptrace_data_t sto;
1571         siptrace_info_t* info;
1572         int faked = 0;
1573         struct sip_msg *msg;
1574         struct sip_msg *req;
1575         struct ip_addr to_ip;
1576         char statusbuf[INT2STR_MAX_LEN];
1577         dest_info_t *dst;
1578
1579         if(t == NULL || t->uas.request == 0 || ps == NULL) {
1580                 LM_DBG("no uas request, local transaction\n");
1581                 return;
1582         }
1583
1584         if(ps->flags & TMCB_RETR_F) {
1585                 LM_DBG("retransmission\n");
1586                 return;
1587         }
1588
1589         info = (siptrace_info_t *)(*ps->param);
1590
1591         memset(&sto, 0, sizeof(siptrace_data_t));
1592
1593         /* can't(don't know) set FL_SIPTRACE flag from trace_onreq_out because
1594          * there no access to CANCEL transaction there */
1595         if (likely(type != TMCB_RESPONSE_READY)) {
1596                 if(traced_user_avp.n != 0)
1597                         sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1598                                         &sto.avp_value, &sto.state);
1599
1600                 if((sto.avp == NULL) && trace_is_off(t->uas.request)) {
1601                         LM_DBG("trace off...\n");
1602                         return;
1603                 }
1604         }
1605
1606         req = ps->req;
1607         msg = ps->rpl;
1608         if(msg == NULL || msg == FAKED_REPLY) {
1609                 msg = t->uas.request;
1610                 faked = 1;
1611         }
1612
1613         if(sip_trace_prepare(msg) < 0)
1614                 return;
1615
1616         if(faked == 0) {
1617                 if(ps->send_buf.len > 0) {
1618                         sto.body = ps->send_buf;
1619                 } else if(t->uas.response.buffer != NULL) {
1620                         sto.body.s = t->uas.response.buffer;
1621                         sto.body.len = t->uas.response.buffer_len;
1622                 } else if(msg->len > 0) {
1623                         sto.body.s = msg->buf;
1624                         sto.body.len = msg->len;
1625                 } else {
1626                         sto.body.s = "No reply buffer";
1627                         sto.body.len = sizeof("No reply buffer") - 1;
1628                 }
1629         } else {
1630                 if(ps->send_buf.len > 0) {
1631                         sto.body = ps->send_buf;
1632                 } else if(t->uas.response.buffer != NULL) {
1633                         sto.body.s = t->uas.response.buffer;
1634                         sto.body.len = t->uas.response.buffer_len;
1635                 } else {
1636                         sto.body.s = "No reply buffer";
1637                         sto.body.len = sizeof("No reply buffer") - 1;
1638                 }
1639         }
1640
1641         sto.callid = msg->callid->body;
1642         sto.method = get_cseq(msg)->method;
1643
1644         if(trace_local_ip.s && trace_local_ip.len > 0) {
1645                 sto.fromip = trace_local_ip;
1646         } else {
1647                 sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1648                                 siptrace_proto_name(msg->rcv.proto),
1649                                 ip_addr2a(&req->rcv.dst_ip), (int)req->rcv.dst_port);
1650                 if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1651                         LM_ERR("failed to format fromip buffer (%d)\n", sto.fromip.len);
1652                         sto.fromip.s = SIPTRACE_ANYADDR;
1653                         sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1654                 } else {
1655                         sto.fromip.s = sto.fromip_buff;
1656                 }
1657         }
1658
1659         sto.status.s = int2strbuf(ps->code, statusbuf, INT2STR_MAX_LEN, &sto.status.len);
1660         if(sto.status.s == 0) {
1661                 LM_ERR("failure to get the status string\n");
1662                 return;
1663         }
1664
1665         memset(&to_ip, 0, sizeof(struct ip_addr));
1666         dst = ps->dst;
1667         if(dst == 0) {
1668                 sto.toip.s = SIPTRACE_ANYADDR;
1669                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1670         } else {
1671                 su2ip_addr(&to_ip, &dst->to);
1672                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1673                                 siptrace_proto_name(dst->proto),
1674                                 ip_addr2a(&to_ip), (int)su_getport(&dst->to));
1675                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1676                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1677                         sto.toip.s = SIPTRACE_ANYADDR;
1678                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1679                 } else {
1680                         sto.toip.s = sto.toip_buff;
1681                 }
1682         }
1683
1684         sto.dir = "out";
1685         sto.fromtag = get_from(msg)->tag_value;
1686         sto.totag = get_to(msg)->tag_value;
1687
1688 #ifdef STATISTICS
1689         sto.stat = siptrace_rpl;
1690 #endif
1691
1692         if (info->uriState == STRACE_RAW_URI) {
1693                 LM_BUG("uriState must be either UNUSED or PARSED here! must be a bug! Message won't be traced!\n");
1694                 return;
1695         }
1696
1697         sip_trace_store(&sto, info->uriState == STRACE_PARSED_URI ? &info->u.dest_info : NULL, NULL);
1698 }
1699
1700 static void trace_tm_neg_ack_in(struct cell *t, int type, struct tmcb_params *ps)
1701 {
1702         siptrace_info_t* info = (siptrace_info_t *)(*ps->param);
1703
1704         LM_DBG("storing negative ack...\n");
1705         /* this condition should not exist but there seems to be a BUG in kamailio
1706          * letting requests other than the ACK inside */
1707         if (ps->req->first_line.u.request.method_value != METHOD_ACK) {
1708                 return;
1709         }
1710
1711         if (info->uriState == STRACE_RAW_URI) {
1712                 LM_BUG("uriState must be either UNUSED or PARSED here! must be a bug! Message won't be traced!\n");
1713                 return;
1714         }
1715
1716
1717         sip_trace(ps->req, (info->uriState == STRACE_PARSED_URI) ? &info->u.dest_info : NULL,
1718                         NULL, NULL);
1719 }
1720
1721 /**
1722  * if any param inside info structure is NULL or has 0 length it will not be added
1723  * if no param set data will have allocated 2 bytes and length 0
1724  * if at least one param has length > 0
1725  *
1726  * data format:
1727  *
1728  * | total length | duri_length | duri*   | corr id length | corr id*
1729  * | 2 bytes      | 2 bytes     | x bytes | 2 bytes        | x bytes
1730  * params marked with * are optional
1731  *
1732  */
1733 static int add_info_xavp(siptrace_info_t* info)
1734 {
1735         sr_xval_t xval;
1736
1737         if (info == NULL) {
1738                 LM_ERR("Nothing to serialize!\n");
1739                 return -1;
1740         }
1741
1742         if (info->uriState != STRACE_RAW_URI) {
1743                 LM_BUG("URI should be in raw format here\n");
1744                 return -1;
1745         }
1746
1747         memset(&xval, 0, sizeof(sr_xval_t));
1748         xval.type = SR_XTYPE_VPTR;
1749         xval.v.vptr = (void *)info;
1750
1751         /* save data into avp */
1752         if (xavp_add_value(&xavp_trace_info_name_s, &xval, NULL) == NULL) {
1753                 shm_free(info);
1754                 LM_ERR("Failed to add xavp!\n");
1755                 return -1;
1756         }
1757
1758         return 0;
1759 }
1760
1761 static inline int parse_raw_uri(siptrace_info_t* info)
1762 {
1763         dest_info_t dest_info;
1764
1765         if (info == NULL) {
1766                 LM_ERR("bad function call\n");
1767                 return -1;
1768         }
1769
1770         if (info->uriState != STRACE_RAW_URI) {
1771                 LM_ERR("Invalid call! siptrace_info must contain a sip uri string!\n");
1772                 return -1;
1773         }
1774
1775         /* parse uri and get dest_info structure */
1776         if (parse_siptrace_uri(&info->u.dup_uri, &dest_info) < 0) {
1777                 LM_ERR("failed to parse uri!\n");
1778                 return -1;
1779         }
1780
1781         info->u.dest_info = dest_info;
1782         info->uriState = STRACE_PARSED_URI;
1783
1784         return 0;
1785 }
1786
1787 static void trace_sl_ack_in(sl_cbp_t *slcbp)
1788 {
1789         sip_msg_t *req;
1790         LM_DBG("storing ack...\n");
1791         req = slcbp->req;
1792         sip_trace(req, 0, NULL, NULL);
1793 }
1794
1795 static void trace_sl_onreply_out(sl_cbp_t *slcbp)
1796 {
1797         sip_msg_t *req;
1798         siptrace_data_t sto;
1799         sip_msg_t *msg;
1800         ip_addr_t to_ip;
1801         char statusbuf[INT2STR_MAX_LEN];
1802
1803         if(slcbp == NULL || slcbp->req == NULL) {
1804                 LM_ERR("bad parameters\n");
1805                 return;
1806         }
1807         req = slcbp->req;
1808
1809         memset(&sto, 0, sizeof(siptrace_data_t));
1810         if(traced_user_avp.n != 0)
1811                 sto.avp = search_first_avp(traced_user_avp_type, traced_user_avp,
1812                                 &sto.avp_value, &sto.state);
1813
1814         if((sto.avp == NULL) && trace_is_off(req)) {
1815                 LM_DBG("trace off...\n");
1816                 return;
1817         }
1818
1819         msg = req;
1820
1821         if(sip_trace_prepare(msg) < 0)
1822                 return;
1823
1824         sto.body.s = (slcbp->reply) ? slcbp->reply->s : "";
1825         sto.body.len = (slcbp->reply) ? slcbp->reply->len : 0;
1826
1827         sto.callid = msg->callid->body;
1828         sto.method = msg->first_line.u.request.method;
1829
1830         if(trace_local_ip.len > 0) {
1831                 sto.fromip = trace_local_ip;
1832         } else {
1833                 sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1834                                 siptrace_proto_name(req->rcv.proto),
1835                                 ip_addr2a(&req->rcv.dst_ip), req->rcv.dst_port);
1836                 if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
1837                         LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
1838                         sto.fromip.s = SIPTRACE_ANYADDR;
1839                         sto.fromip.len = SIPTRACE_ANYADDR_LEN;
1840                 } else {
1841                         sto.fromip.s = sto.fromip_buff;
1842                 }
1843         }
1844
1845         sto.status.s = int2strbuf(slcbp->code, statusbuf, INT2STR_MAX_LEN, &sto.status.len);
1846         if(sto.status.s == 0) {
1847                 LM_ERR("failure to get the status string\n");
1848                 return;
1849         }
1850
1851         memset(&to_ip, 0, sizeof(struct ip_addr));
1852         if(slcbp->dst == 0) {
1853                 sto.toip.s = SIPTRACE_ANYADDR;
1854                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
1855         } else {
1856                 su2ip_addr(&to_ip, &slcbp->dst->to);
1857                 sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
1858                                 siptrace_proto_name(req->rcv.proto), ip_addr2a(&to_ip),
1859                                 (int)su_getport(&slcbp->dst->to));
1860                 if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
1861                         LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
1862                         sto.toip.s = SIPTRACE_ANYADDR;
1863                         sto.toip.len = SIPTRACE_ANYADDR_LEN;
1864                 } else {
1865                         sto.toip.s = sto.toip_buff;
1866                 }
1867         }
1868
1869         sto.dir = "out";
1870         sto.fromtag = get_from(msg)->tag_value;
1871         sto.totag = get_to(msg)->tag_value;
1872
1873 #ifdef STATISTICS
1874         sto.stat = siptrace_rpl;
1875 #endif
1876
1877         sip_trace_store(&sto, NULL, NULL);
1878         return;
1879 }
1880
1881 static void trace_transaction(sip_msg_t* msg, siptrace_info_t* info, int dlg_tran)
1882 {
1883         if(msg == NULL) {
1884                 LM_DBG("nothing to trace\n");
1885                 return;
1886         }
1887
1888         /* trace current message on out */
1889         msg->msg_flags |= FL_SIPTRACE;
1890         if (info->uriState == STRACE_RAW_URI) {
1891                 if (parse_raw_uri(info) < 0) {
1892                         LM_ERR("failed to parse trace destination uri!\n");
1893                         return;
1894                 }
1895         }
1896
1897         if(tmb.register_tmcb(msg, 0, TMCB_REQUEST_SENT, trace_onreq_out, info, 0) <= 0) {
1898                 LM_ERR("can't register trace_onreq_out\n");
1899                 return;
1900         }
1901
1902         /* trace reply on in */
1903         if(tmb.register_tmcb(msg, 0, TMCB_RESPONSE_IN, trace_onreply_in, info, 0) <= 0) {
1904                 LM_ERR("can't register trace_onreply_in\n");
1905                 return;
1906         }
1907
1908         /* trace reply on out */
1909         if(tmb.register_tmcb(msg, 0, TMCB_RESPONSE_SENT, trace_onreply_out, info,
1910                                                         dlg_tran ? 0 : free_trace_info)
1911                         <= 0) {
1912                 LM_ERR("can't register trace_onreply_out\n");
1913                 return;
1914         }
1915
1916         /* TODO */
1917         /* check the following callbacks: TMCB_REQUEST_PENDING, TMCB_RESPONSE_READY, TMCB_ACK_NEG_IN */
1918         /* trace reply on in */
1919         if(tmb.register_tmcb(msg, 0, TMCB_ACK_NEG_IN, trace_tm_neg_ack_in, info, 0) <= 0) {
1920                 LM_ERR("can't register trace_onreply_in\n");
1921                 return;
1922         }
1923
1924         if(tmb.register_tmcb(msg, 0, TMCB_E2ECANCEL_IN, trace_cancel_in, info, 0) <= 0) {
1925                 LM_ERR("can't register trace_onreply_in\n");
1926                 return;
1927         }
1928 }
1929
1930 //static void trace_dialog(sip_msg_t* msg, siptrace_info_t* info)
1931 static void trace_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params *params)
1932 {
1933         sr_xavp_t* xavp;
1934
1935         if (!dlgb.get_dlg) {
1936                 LM_ERR("Dialog API not loaded! Trace off...\n");
1937                 return;
1938         }
1939
1940         /* request - params->req */
1941         if (params == NULL || params->req == NULL) {
1942                 LM_ERR("Invalid args!\n");
1943                 return;
1944         }
1945
1946         if (!(params->req->msg_flags & FL_SIPTRACE)) {
1947                 LM_DBG("Trace is off for this request...\n");
1948                 return;
1949         }
1950
1951         xavp = xavp_get(&xavp_trace_info_name_s, NULL);
1952         if (!xavp) {
1953                 /* this actually happens when only the transaction is traced
1954                  * FL_SIPTRACE is set from trace_onreq_out
1955                  * but xavp is set only for dialogs so this will avoid
1956                  * registering dialog callbacks which is the desired behavior */
1957                 LM_DBG("%.*s xavp not registered! "
1958                                 "Probably incoming E2E CANCEL!\n", xavp_trace_info_name_s.len,
1959                                 xavp_trace_info_name_s.s);
1960                 return;
1961         }
1962
1963         if(dlgb.register_dlgcb(dlg, DLGCB_REQ_WITHIN,
1964                                 trace_dialog_transaction, xavp->val.v.vptr, 0) != 0) {
1965                 LM_ERR("Failed to register DLGCB_REQ_WITHIN callback!\n");
1966                 return;
1967         }
1968
1969         if(dlgb.register_dlgcb(dlg, DLGCB_TERMINATED,
1970                                 trace_dialog_transaction, xavp->val.v.vptr, free_trace_info) != 0) {
1971                 LM_ERR("Failed to register DLGCB_TERMINATED callback!\n");
1972                 return;
1973         }
1974
1975         return;
1976 }
1977
1978
1979 static void trace_dialog_transaction(struct dlg_cell* dlg, int type, struct dlg_cb_params *params)
1980 {
1981         siptrace_info_t* info;
1982
1983         /* coverity fix - there shouldn't be a scenario for this to happen */
1984         if (params == NULL || params->param == NULL) {
1985                 LM_ERR("NULL dialog params!\n");
1986                 return;
1987         }
1988
1989         /**
1990          * DUAL BYE - internally generated BYE from kamailio
1991          * set flag to signal request_in callback which will register
1992          * transaction callbacks to catch caller and callee BYEs and their
1993          * responses
1994          */
1995         if (params->req == NULL && params->rpl == NULL) {
1996                 LM_DBG("dual bye!\n");
1997                 return;
1998         }
1999         info = (siptrace_info_t *)*params->param;
2000
2001         trace_transaction(params->req, info, 1);
2002
2003         sip_trace(params->req, &info->u.dest_info, &info->correlation_id, NULL);
2004 }
2005
2006 static void free_trace_info(void* trace_info)
2007 {
2008         if (!trace_info) return;
2009
2010         shm_free(trace_info);
2011 }
2012
2013 /**
2014  *
2015  */
2016 int siptrace_net_data_recv(sr_event_param_t *evp)
2017 {
2018         sr_net_info_t *nd;
2019         siptrace_data_t sto;
2020         sip_msg_t tmsg;
2021
2022         if(evp->data == 0)
2023                 return -1;
2024
2025         if(trace_on_flag != NULL && *trace_on_flag==0) {
2026                 return 0;
2027         }
2028
2029         nd = (sr_net_info_t *)evp->data;
2030         if(nd->rcv == NULL || nd->data.s == NULL || nd->data.len <= 0) {
2031                 return -1;
2032         }
2033
2034         memset(&sto, 0, sizeof(siptrace_data_t));
2035
2036         sto.body.s = nd->data.s;
2037         sto.body.len = nd->data.len;
2038
2039         sto.fromip.len = snprintf(sto.fromip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
2040                         siptrace_proto_name(nd->rcv->proto),
2041                         ip_addr2a(&nd->rcv->src_ip), (int)nd->rcv->src_port);
2042         if(sto.fromip.len<0 || sto.fromip.len>=SIPTRACE_ADDR_MAX) {
2043                 LM_ERR("failed to format toip buffer (%d)\n", sto.fromip.len);
2044                 sto.fromip.s = SIPTRACE_ANYADDR;
2045                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
2046         } else {
2047                 sto.fromip.s = sto.fromip_buff;
2048         }
2049
2050         sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
2051                         siptrace_proto_name(nd->rcv->proto), ip_addr2a(&nd->rcv->dst_ip),
2052                         (int)nd->rcv->dst_port);
2053         if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
2054                 LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
2055                 sto.toip.s = SIPTRACE_ANYADDR;
2056                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
2057         } else {
2058                 sto.toip.s = sto.toip_buff;
2059         }
2060
2061         sto.dir = "in";
2062
2063         if(_siptrace_mode & SIPTRACE_MODE_HEP) {
2064                 trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL, NULL);
2065         }
2066
2067         if(_siptrace_mode & SIPTRACE_MODE_DB) {
2068                 memset(&tmsg, 0, sizeof(sip_msg_t));
2069                 tmsg.buf = sto.body.s;
2070                 tmsg.len = sto.body.len;
2071
2072                 if (parse_msg(tmsg.buf, tmsg.len, &tmsg)!=0) {
2073                         LM_DBG("msg buffer parsing failed!");
2074                         goto afterdb;
2075                 }
2076
2077                 if(sip_trace_prepare(&tmsg) < 0) {
2078                         free_sip_msg(&tmsg);
2079                         goto afterdb;
2080                 }
2081
2082                 sto.callid = tmsg.callid->body;
2083                 if(tmsg.first_line.type == SIP_REQUEST) {
2084                         sto.method = tmsg.first_line.u.request.method;
2085                 } else {
2086                         sto.method = get_cseq(&tmsg)->method;
2087                 }
2088
2089                 if(tmsg.first_line.type == SIP_REPLY) {
2090                         sto.status = tmsg.first_line.u.reply.status;
2091                 } else {
2092                         sto.status.s = "";
2093                         sto.status.len = 0;
2094                 }
2095                 sto.fromtag = get_from(&tmsg)->tag_value;
2096                 sto.totag = get_to(&tmsg)->tag_value;
2097
2098                 gettimeofday(&sto.tv, NULL);
2099                 sip_trace_store_db(&sto);
2100
2101                 free_sip_msg(&tmsg);
2102         }
2103
2104 afterdb:
2105         if(_siptrace_mode & SIPTRACE_MODE_URI) {
2106                 trace_send_duplicate(sto.body.s, sto.body.len, NULL);
2107         }
2108
2109         return 0;
2110 }
2111
2112 /**
2113  *
2114  */
2115 int siptrace_net_data_send(sr_event_param_t *evp)
2116 {
2117         sr_net_info_t *nd;
2118         dest_info_t new_dst;
2119         siptrace_data_t sto;
2120         sip_msg_t tmsg;
2121
2122         if(evp->data == 0)
2123                 return -1;
2124
2125         if(trace_on_flag != NULL && *trace_on_flag==0) {
2126                 return 0;
2127         }
2128
2129         nd = (sr_net_info_t *)evp->data;
2130         if(nd->dst == NULL || nd->data.s == NULL || nd->data.len <= 0)
2131                 return -1;
2132
2133         new_dst = *nd->dst;
2134
2135         if(new_dst.send_sock == 0) {
2136                 new_dst.send_sock = get_send_socket(0, &nd->dst->to, nd->dst->proto);
2137         }
2138
2139         memset(&sto, 0, sizeof(siptrace_data_t));
2140
2141         sto.body.s = nd->data.s;
2142         sto.body.len = nd->data.len;
2143
2144         if(unlikely(new_dst.send_sock == 0)) {
2145                 LM_WARN("no sending socket found\n");
2146                 strcpy(sto.fromip_buff, SIPTRACE_ANYADDR);
2147                 sto.fromip.len = SIPTRACE_ANYADDR_LEN;
2148         } else {
2149                 if(new_dst.send_sock->sock_str.len>=SIPTRACE_ADDR_MAX-1) {
2150                         LM_ERR("socket string is too large: %d\n",
2151                                         new_dst.send_sock->sock_str.len);
2152                         goto error;
2153                 }
2154                 strncpy(sto.fromip_buff, new_dst.send_sock->sock_str.s,
2155                                 new_dst.send_sock->sock_str.len);
2156                 sto.fromip.len = new_dst.send_sock->sock_str.len;
2157         }
2158         sto.fromip.s = sto.fromip_buff;
2159
2160         sto.toip.len = snprintf(sto.toip_buff, SIPTRACE_ADDR_MAX, "%s:%s:%d",
2161                         siptrace_proto_name(new_dst.send_sock->proto),
2162                         suip2a(&new_dst.to, sizeof(new_dst.to)),
2163                         (int)su_getport(&new_dst.to));
2164         if(sto.toip.len<0 || sto.toip.len>=SIPTRACE_ADDR_MAX) {
2165                 LM_ERR("failed to format toip buffer (%d)\n", sto.toip.len);
2166                 sto.toip.s = SIPTRACE_ANYADDR;
2167                 sto.toip.len = SIPTRACE_ANYADDR_LEN;
2168         } else {
2169                 sto.toip.s = sto.toip_buff;
2170         }
2171
2172         sto.dir = "out";
2173
2174         if(_siptrace_mode & SIPTRACE_MODE_HEP) {
2175                 trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL, NULL);
2176         }
2177
2178         if(_siptrace_mode & SIPTRACE_MODE_DB) {
2179                 memset(&tmsg, 0, sizeof(sip_msg_t));
2180                 tmsg.buf = sto.body.s;
2181                 tmsg.len = sto.body.len;
2182
2183                 if (parse_msg(tmsg.buf, tmsg.len, &tmsg)!=0) {
2184                         LM_DBG("msg buffer parsing failed!");
2185                         goto afterdb;
2186                 }
2187
2188                 if(sip_trace_prepare(&tmsg) < 0) {
2189                         free_sip_msg(&tmsg);
2190                         goto afterdb;
2191                 }
2192
2193                 sto.callid = tmsg.callid->body;
2194                 if(tmsg.first_line.type == SIP_REQUEST) {
2195                         sto.method = tmsg.first_line.u.request.method;
2196                 } else {
2197                         sto.method = get_cseq(&tmsg)->method;
2198                 }
2199
2200                 if(tmsg.first_line.type == SIP_REPLY) {
2201                         sto.status = tmsg.first_line.u.reply.status;
2202                 } else {
2203                         sto.status.s = "";
2204                         sto.status.len = 0;
2205                 }
2206                 sto.fromtag = get_from(&tmsg)->tag_value;
2207                 sto.totag = get_to(&tmsg)->tag_value;
2208
2209                 gettimeofday(&sto.tv, NULL);
2210                 sip_trace_store_db(&sto);
2211
2212                 free_sip_msg(&tmsg);
2213         }
2214
2215 afterdb:
2216         if(_siptrace_mode & SIPTRACE_MODE_URI) {
2217                 trace_send_duplicate(sto.body.s, sto.body.len, NULL);
2218         }
2219
2220         return 0;
2221
2222 error:
2223         return -1;
2224 }
2225
2226 /**
2227  *
2228  */
2229 static int w_hlog1(struct sip_msg *msg, char *message, char *_)
2230 {
2231         str smessage;
2232         if(fixup_get_svalue(msg, (gparam_t *)message, &smessage) != 0) {
2233                 LM_ERR("unable to parse the message\n");
2234                 return -1;
2235         }
2236         return hlog(msg, NULL, &smessage);
2237 }
2238
2239 /**
2240  *
2241  */
2242 static int ki_hlog(sip_msg_t *msg, str *message)
2243 {
2244         return hlog(msg, NULL, message);
2245 }
2246
2247 /**
2248  *
2249  */
2250 static int w_hlog2(struct sip_msg *msg, char *correlationid, char *message)
2251 {
2252         str scorrelationid, smessage;
2253         if(fixup_get_svalue(msg, (gparam_t *)correlationid, &scorrelationid) != 0) {
2254                 LM_ERR("unable to parse the correlation id\n");
2255                 return -1;
2256         }
2257         if(fixup_get_svalue(msg, (gparam_t *)message, &smessage) != 0) {
2258                 LM_ERR("unable to parse the message\n");
2259                 return -1;
2260         }
2261         return hlog(msg, &scorrelationid, &smessage);
2262 }
2263
2264 /**
2265  *
2266  */
2267 static int ki_hlog_cid(sip_msg_t *msg, str *correlationid, str *message)
2268 {
2269         return hlog(msg, correlationid, message);
2270 }
2271
2272 /**
2273  *
2274  */
2275 static void siptrace_rpc_status(rpc_t *rpc, void *c)
2276 {
2277         str status = {0, 0};
2278
2279         if(rpc->scan(c, "S", &status) < 1) {
2280                 rpc->fault(c, 500, "Not enough parameters (on, off or check)");
2281                 return;
2282         }
2283
2284         if(trace_on_flag == NULL) {
2285                 rpc->fault(c, 500, "Internal error");
2286                 return;
2287         }
2288
2289         if(strncasecmp(status.s, "on", strlen("on")) == 0) {
2290                 *trace_on_flag = 1;
2291                 rpc->rpl_printf(c, "Enabled");
2292                 return;
2293         }
2294         if(strncasecmp(status.s, "off", strlen("off")) == 0) {
2295                 *trace_on_flag = 0;
2296                 rpc->rpl_printf(c, "Disabled");
2297                 return;
2298         }
2299         if(strncasecmp(status.s, "check", strlen("check")) == 0) {
2300                 rpc->rpl_printf(c, *trace_on_flag ? "Enabled" : "Disabled");
2301                 return;
2302         }
2303         rpc->fault(c, 500, "Bad parameter (on, off or check)");
2304         return;
2305 }
2306
2307 static const char *siptrace_status_doc[2] = {
2308         "Get status or turn on/off siptrace. Parameters: on, off or check.",
2309         0
2310 };
2311
2312 rpc_export_t siptrace_rpc[] = {
2313         {"siptrace.status", siptrace_rpc_status, siptrace_status_doc, 0},
2314         {0, 0, 0, 0}
2315 };
2316
2317 static int siptrace_init_rpc(void)
2318 {
2319         if(rpc_register_array(siptrace_rpc) != 0) {
2320                 LM_ERR("failed to register RPC commands\n");
2321                 return -1;
2322         }
2323         return 0;
2324 }
2325
2326 /**
2327  *
2328  */
2329 /* clang-format off */
2330 static sr_kemi_t sr_kemi_siptrace_exports[] = {
2331         { str_init("siptrace"), str_init("sip_trace"),
2332                 SR_KEMIP_INT, ki_sip_trace,
2333                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
2334                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2335         },
2336         { str_init("siptrace"), str_init("sip_trace_dst"),
2337                 SR_KEMIP_INT, ki_sip_trace_dst,
2338                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2339                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2340         },
2341         { str_init("siptrace"), str_init("sip_trace_dst_cid"),
2342                 SR_KEMIP_INT, ki_sip_trace_dst_cid,
2343                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2344                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2345         },
2346         { str_init("siptrace"), str_init("sip_trace_dst_cid_type"),
2347                 SR_KEMIP_INT, ki_sip_trace_dst_cid_flag,
2348                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
2349                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2350         },
2351         { str_init("siptrace"), str_init("hlog"),
2352                 SR_KEMIP_INT, ki_hlog,
2353                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2354                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2355         },
2356         { str_init("siptrace"), str_init("hlog_cid"),
2357                 SR_KEMIP_INT, ki_hlog_cid,
2358                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2359                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2360         },
2361         { str_init("siptrace"), str_init("sip_trace_mode"),
2362                 SR_KEMIP_INT, ki_sip_trace_mode,
2363                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2364                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2365         },
2366
2367         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
2368 };
2369 /* clang-format on */
2370
2371 /**
2372  *
2373  */
2374 int mod_register(char *path, int *dlflags, void *p1, void *p2)
2375 {
2376         sr_kemi_modules_add(sr_kemi_siptrace_exports);
2377         return 0;
2378 }