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