everything: shotgun attempt to put PROTO_WS and PROTO_WSS across core and in modules...
[sip-router] / modules_k / siptrace / siptrace.c
1 /* 
2  * $Id$ 
3  *
4  * siptrace module - helper module to trace sip messages
5  *
6  * Copyright (C) 2006 Voice Sistem S.R.L.
7  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
8  *
9  * This file is part of Kamailio, a free SIP server.
10  *
11  * Kamailio is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version
15  *
16  * Kamailio is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License 
22  * along with this program; if not, write to the Free Software 
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  *
25  */
26
27 /*! \file
28  * siptrace module - helper module to trace sip messages
29  *
30  */
31
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include "../../sr_module.h"
38 #include "../../dprint.h"
39 #include "../../ut.h"
40 #include "../../ip_addr.h"
41 #include "../../mem/mem.h"
42 #include "../../mem/shm_mem.h"
43 #include "../../lib/kmi/mi.h"
44 #include "../../lib/srdb1/db.h"
45 #include "../../parser/parse_content.h"
46 #include "../../parser/parse_from.h"
47 #include "../../parser/parse_cseq.h"
48 #include "../../pvar.h"
49 #include "../../modules/tm/tm_load.h"
50 #include "../../modules/sl/sl.h"
51 #include "../../str.h"
52 #include "../../onsend.h"
53
54 #include "../../modules/sipcapture/sipcapture.h"
55
56 #ifdef STATISTICS
57 #include "../../lib/kcore/statistics.h"
58 #endif
59
60 MODULE_VERSION
61
62 struct _siptrace_data {
63         struct usr_avp *avp;
64         int_str avp_value;
65         struct search_state state;
66         str body;
67         str callid;
68         str method;
69         str status;
70         char *dir;
71         str fromtag;
72         str fromip;
73         str toip;
74         char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
75         char fromip_buff[IP_ADDR_MAX_STR_SIZE+12];
76         struct timeval tv;
77 #ifdef STATISTICS
78         stat_var *stat;
79 #endif
80 };
81
82 struct tm_binds tmb;
83
84 /** SL API structure */
85 sl_api_t slb;
86
87 /* module function prototypes */
88 static int mod_init(void);
89 static int child_init(int rank);
90 static void destroy(void);
91 static int sip_trace(struct sip_msg*, char*, char*);
92
93 static int sip_trace_store_db(struct _siptrace_data* sto);
94 static int trace_send_duplicate(char *buf, int len);
95
96 static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps);
97 static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps);
98 static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps);
99 static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps);
100 static void trace_sl_onreply_out(sl_cbp_t *slcb);
101 static void trace_sl_ack_in(sl_cbp_t *slcb);
102
103 static int trace_send_hep_duplicate(str *body, str *from, str *to);
104 static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto);
105
106
107 static struct mi_root* sip_trace_mi(struct mi_root* cmd, void* param );
108
109 static str db_url             = str_init(DEFAULT_RODB_URL);
110 static str siptrace_table     = str_init("sip_trace");
111 static str date_column        = str_init("time_stamp");  /* 00 */
112 static str callid_column      = str_init("callid");      /* 01 */
113 static str traced_user_column = str_init("traced_user"); /* 02 */
114 static str msg_column         = str_init("msg");         /* 03 */
115 static str method_column      = str_init("method");      /* 04 */
116 static str status_column      = str_init("status");      /* 05 */
117 static str fromip_column      = str_init("fromip");      /* 06 */
118 static str toip_column        = str_init("toip");        /* 07 */
119 static str fromtag_column     = str_init("fromtag");     /* 08 */
120 static str direction_column   = str_init("direction");   /* 09 */
121 static str time_us_column     = str_init("time_us");     /* 10 */
122
123 #define NR_KEYS 11
124
125 #define XHEADERS_BUFSIZE 512
126
127 int trace_flag = -1;
128 int trace_on   = 0;
129 int trace_sl_acks = 1;
130
131 int trace_to_database = 1;
132 int trace_delayed = 0;
133
134 int hep_version = 1;
135 int hep_capture_id = 1;
136
137 int xheaders_write = 0;
138 int xheaders_read = 0;
139
140 str    dup_uri_str      = {0, 0};
141 struct sip_uri *dup_uri = 0;
142
143 int *trace_on_flag = NULL;
144 int *trace_to_database_flag = NULL;
145
146 int *xheaders_write_flag = NULL;
147 int *xheaders_read_flag = NULL;
148
149 static unsigned short traced_user_avp_type = 0;
150 static int_str traced_user_avp;
151 static str traced_user_avp_str = {NULL, 0};
152
153 static unsigned short trace_table_avp_type = 0;
154 static int_str trace_table_avp;
155 static str trace_table_avp_str = {NULL, 0};
156
157 static str trace_local_ip = {NULL, 0};
158
159 int hep_mode_on = 0;
160
161 db1_con_t *db_con = NULL;               /*!< database connection */
162 db_func_t db_funcs;                     /*!< Database functions */
163
164 /*! \brief
165  * Exported functions
166  */
167 static cmd_export_t cmds[] = {
168         {"sip_trace", (cmd_function)sip_trace, 0, 0, 0, ANY_ROUTE},
169         {"sip_trace", (cmd_function)sip_trace, 1, 0, 0, ANY_ROUTE},
170         {0, 0, 0, 0, 0, 0}
171 };
172
173
174 /*! \brief
175  * Exported parameters
176  */
177 static param_export_t params[] = {
178         {"db_url",             STR_PARAM, &db_url.s             },
179         {"table",              STR_PARAM, &siptrace_table.s     },
180         {"date_column",        STR_PARAM, &date_column.s        },
181         {"callid_column",      STR_PARAM, &callid_column.s      },
182         {"traced_user_column", STR_PARAM, &traced_user_column.s },
183         {"msg_column",         STR_PARAM, &msg_column.s         },
184         {"method_column",      STR_PARAM, &method_column.s      },
185         {"status_column",      STR_PARAM, &status_column.s      },
186         {"fromip_column",      STR_PARAM, &fromip_column.s      },
187         {"toip_column",        STR_PARAM, &toip_column.s        },
188         {"fromtag_column",     STR_PARAM, &fromtag_column.s     },
189         {"direction_column",   STR_PARAM, &direction_column.s   },
190         {"trace_flag",         INT_PARAM, &trace_flag           },
191         {"trace_on",           INT_PARAM, &trace_on             },
192         {"traced_user_avp",    STR_PARAM, &traced_user_avp_str.s},
193         {"trace_table_avp",    STR_PARAM, &trace_table_avp_str.s},
194         {"duplicate_uri",      STR_PARAM, &dup_uri_str.s        },
195         {"trace_to_database",  INT_PARAM, &trace_to_database    },
196         {"trace_local_ip",     STR_PARAM, &trace_local_ip.s     },
197         {"trace_sl_acks",      INT_PARAM, &trace_sl_acks        },
198         {"xheaders_write",     INT_PARAM, &xheaders_write       },
199         {"xheaders_read",      INT_PARAM, &xheaders_read        },
200         {"hep_mode_on",        INT_PARAM, &hep_mode_on          },       
201         {"hep_version",        INT_PARAM, &hep_version          },
202         {"hep_capture_id",     INT_PARAM, &hep_capture_id       },              
203         {"trace_delayed",      INT_PARAM, &trace_delayed        },
204         {0, 0, 0}
205 };
206
207 /*! \brief
208  * MI commands
209  */
210 static mi_export_t mi_cmds[] = {
211         { "sip_trace", sip_trace_mi,   0,  0,  0 },
212         { 0, 0, 0, 0, 0}
213 };
214
215
216 #ifdef STATISTICS
217 stat_var* siptrace_req;
218 stat_var* siptrace_rpl;
219
220 stat_export_t siptrace_stats[] = {
221         {"traced_requests" ,  0,  &siptrace_req  },
222         {"traced_replies"  ,  0,  &siptrace_rpl  },
223         {0,0,0}
224 };
225 #endif
226
227 /*! \brief module exports */
228 struct module_exports exports = {
229         "siptrace", 
230         DEFAULT_DLFLAGS, /*!< dlopen flags */
231         cmds,       /*!< Exported functions */
232         params,     /*!< Exported parameters */
233 #ifdef STATISTICS
234         siptrace_stats,  /*!< exported statistics */
235 #else
236         0,          /*!< exported statistics */
237 #endif
238         mi_cmds,    /*!< exported MI functions */
239         0,          /*!< exported pseudo-variables */
240         0,          /*!< extra processes */
241         mod_init,   /*!< module initialization function */
242         0,          /*!< response function */
243         destroy,    /*!< destroy function */
244         child_init  /*!< child initialization function */
245 };
246
247
248 /*! \brief Initialize siptrace module */
249 static int mod_init(void)
250 {
251         pv_spec_t avp_spec;
252         sl_cbelem_t slcb;
253
254 #ifdef STATISTICS
255         /* register statistics */
256         if (register_module_stats(exports.name, siptrace_stats)!=0)
257         {
258                 LM_ERR("failed to register core statistics\n");
259                 return -1;
260         }
261 #endif
262
263         if(register_mi_mod(exports.name, mi_cmds)!=0)
264         {
265                 LM_ERR("failed to register MI commands\n");
266                 return -1;
267         }
268
269         db_url.len = strlen(db_url.s);
270         siptrace_table.len = strlen(siptrace_table.s);
271         date_column.len = strlen(date_column.s);
272         callid_column.len = strlen(callid_column.s);
273         traced_user_column.len = strlen(traced_user_column.s);
274         msg_column.len = strlen(msg_column.s);
275         method_column.len = strlen(method_column.s);
276         status_column.len = strlen(status_column.s);
277         fromip_column.len = strlen(fromip_column.s);
278         toip_column.len = strlen(toip_column.s);
279         fromtag_column.len = strlen(fromtag_column.s);
280         direction_column.len = strlen(direction_column.s);
281         if (traced_user_avp_str.s)
282                 traced_user_avp_str.len = strlen(traced_user_avp_str.s);
283         if (trace_table_avp_str.s)
284                 trace_table_avp_str.len = strlen(trace_table_avp_str.s);
285         if (dup_uri_str.s)
286                 dup_uri_str.len = strlen(dup_uri_str.s);
287         if (trace_local_ip.s)
288                 trace_local_ip.len = strlen(trace_local_ip.s);
289
290         if (trace_flag<0 || trace_flag>(int)MAX_FLAG)
291         {
292                 LM_ERR("invalid trace flag %d\n", trace_flag);
293                 return -1;
294         }
295         trace_flag = 1<<trace_flag;
296
297         trace_to_database_flag = (int*)shm_malloc(sizeof(int));
298         if(trace_to_database_flag==NULL) {
299                 LM_ERR("no more shm memory left\n");
300                 return -1;
301         }
302
303         *trace_to_database_flag = trace_to_database;
304
305         /* Find a database module if needed */
306         if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
307                 if (db_bind_mod(&db_url, &db_funcs))
308                 {
309                         LM_ERR("unable to bind database module\n");
310                         return -1;
311                 }
312                 if (trace_to_database_flag && !DB_CAPABILITY(db_funcs, DB_CAP_INSERT))
313                 {
314                         LM_ERR("database modules does not provide all functions needed"
315                                         " by module\n");
316                         return -1;
317                 }
318         }
319
320         if(hep_version != 1 && hep_version != 2) {
321   
322                   LM_ERR("unsupported version of HEP");
323                   return -1;
324         }                                          
325
326
327         trace_on_flag = (int*)shm_malloc(sizeof(int));
328         if(trace_on_flag==NULL) {
329                 LM_ERR("no more shm memory left\n");
330                 return -1;
331         }
332
333         *trace_on_flag = trace_on;
334
335         xheaders_write_flag = (int*)shm_malloc(sizeof(int));
336         xheaders_read_flag = (int*)shm_malloc(sizeof(int));
337         if (!(xheaders_write_flag && xheaders_read_flag)) {
338                 LM_ERR("no more shm memory left\n");
339                 return -1;
340         }
341         *xheaders_write_flag = xheaders_write;
342         *xheaders_read_flag = xheaders_read;
343
344         /* register callbacks to TM */
345         if (load_tm_api(&tmb)!=0) {
346                 LM_WARN("can't load tm api. Will not install tm callbacks.\n");
347         } else if(tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, trace_onreq_in, 0, 0) <=0) {
348                 LM_ERR("can't register trace_onreq_in\n");
349                 return -1;
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                 {
368                         slcb.type = SLCB_ACK_FILTERED;
369                         slcb.cbf  = trace_sl_ack_in;
370                         if (slb.register_cb(&slcb) != 0) {
371                                 LM_ERR("can't register for SLCB_ACK_FILTERED\n");
372                                 return -1;
373                         }
374                 }
375         }
376
377         if(dup_uri_str.s!=0)
378         {
379                 dup_uri_str.len = strlen(dup_uri_str.s);
380                 dup_uri = (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri));
381                 if(dup_uri==0)
382                 {
383                         LM_ERR("no more pkg memory left\n");
384                         return -1;
385                 }
386                 memset(dup_uri, 0, sizeof(struct sip_uri));
387                 if(parse_uri(dup_uri_str.s, dup_uri_str.len, dup_uri)<0)
388                 {
389                         LM_ERR("bad dup uri\n");
390                         return -1;
391                 }
392         }
393
394         if(traced_user_avp_str.s && traced_user_avp_str.len > 0)
395         {
396                 if (pv_parse_spec(&traced_user_avp_str, &avp_spec)==0
397                                 || avp_spec.type!=PVT_AVP)
398                 {
399                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
400                                         traced_user_avp_str.len, traced_user_avp_str.s);
401                         return -1;
402                 }
403
404                 if(pv_get_avp_name(0, &avp_spec.pvp, &traced_user_avp,
405                                         &traced_user_avp_type)!=0)
406                 {
407                         LM_ERR("[%.*s] - invalid AVP definition\n",
408                                         traced_user_avp_str.len, traced_user_avp_str.s);
409                         return -1;
410                 }
411         } else {
412                 traced_user_avp.n = 0;
413                 traced_user_avp_type = 0;
414         }
415         if(trace_table_avp_str.s && trace_table_avp_str.len > 0)
416         {
417                 if (pv_parse_spec(&trace_table_avp_str, &avp_spec)==0
418                                 || avp_spec.type!=PVT_AVP)
419                 {
420                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
421                                         trace_table_avp_str.len, trace_table_avp_str.s);
422                         return -1;
423                 }
424
425                 if(pv_get_avp_name(0, &avp_spec.pvp, &trace_table_avp,
426                                         &trace_table_avp_type)!=0)
427                 {
428                         LM_ERR("[%.*s] - invalid AVP definition\n",
429                                         trace_table_avp_str.len, trace_table_avp_str.s);
430                         return -1;
431                 }
432         } else {
433                 trace_table_avp.n = 0;
434                 trace_table_avp_type = 0;
435         }
436
437         return 0;
438 }
439
440
441 static int child_init(int rank)
442 {
443         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
444                 return 0; /* do nothing for the main process */
445
446         if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
447                 db_con = db_funcs.init(&db_url);
448                 if (!db_con)
449                 {
450                         LM_ERR("unable to connect to database. Please check configuration.\n");
451                         return -1;
452                 }
453         }
454
455         return 0;
456 }
457
458
459 static void destroy(void)
460 {
461         if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
462                 if (db_con!=NULL)
463                         db_funcs.close(db_con);
464         }
465
466         if (trace_on_flag)
467                 shm_free(trace_on_flag);
468
469 }
470
471 static inline int siptrace_copy_proto(int proto, char *buf)
472 {
473         if(buf==0)
474                 return -1;
475         if(proto==PROTO_TCP) {
476                 strcpy(buf, "tcp:");
477         } else if(proto==PROTO_TLS) {
478                 strcpy(buf, "tls:");
479         } else if(proto==PROTO_SCTP) {
480                 strcpy(buf, "sctp:");
481         } else if(proto==PROTO_WS) {
482                 strcpy(buf, "ws:");
483         } else if(proto==PROTO_WSS) {
484                 strcpy(buf, "wss:");
485         } else {
486                 strcpy(buf, "udp:");
487         }
488         return 0;
489 }
490
491 static inline str* siptrace_get_table(void)
492 {
493         static int_str         avp_value;
494         struct usr_avp *avp;
495
496         if(trace_table_avp.n==0)
497                 return &siptrace_table;
498
499         avp = NULL;
500         if(trace_table_avp.n!=0)
501                 avp=search_first_avp(trace_table_avp_type, trace_table_avp, &avp_value,
502                                 0);
503
504         if(avp==NULL || !is_avp_str_val(avp) || avp_value.s.len<=0)
505                 return &siptrace_table;
506
507         return &avp_value.s;
508 }
509
510 static int sip_trace_prepare(sip_msg_t *msg)
511 {
512         if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) {
513                 LM_ERR("cannot parse FROM header\n");
514                 goto error;
515         }
516
517         if(parse_headers(msg, HDR_CALLID_F, 0)!=0 || msg->callid==NULL
518                         || msg->callid->body.s==NULL) {
519                 LM_ERR("cannot parse call-id\n");
520                 goto error;
521         }
522
523         return 0;
524 error:
525         return -1;
526 }
527
528 // Appends x-headers to the message in sto->body containing data from sto
529 static int sip_trace_xheaders_write(struct _siptrace_data *sto)
530 {
531         char* buf = NULL;
532         int bytes_written = 0;
533         char* eoh = NULL;
534         int eoh_offset = 0;
535         char* new_eoh = NULL;
536
537         if(xheaders_write_flag==NULL || *xheaders_write_flag==0)
538                 return 0;
539
540         // Memory for the message with some additional headers.
541         // It gets free()ed in sip_trace_xheaders_free().
542         buf = pkg_malloc(sto->body.len + XHEADERS_BUFSIZE);
543         if (buf == NULL) {
544                 LM_ERR("sip_trace_xheaders_write: out of memory\n");
545                 return -1;
546         }
547
548         // Copy the whole message to buf first; it must be \0-terminated for
549         // strstr() to work. Then search for the end-of-header sequence.
550         memcpy(buf, sto->body.s, sto->body.len);
551         buf[sto->body.len] = '\0';
552         eoh = strstr(buf, "\r\n\r\n");
553         if (eoh == NULL) {
554                 LM_ERR("sip_trace_xheaders_write: malformed message\n");
555                 goto error;
556         }
557         eoh += 2; // the first \r\n belongs to the last header => skip it
558
559         // Write the new headers a the end-of-header position. This overwrites
560         // the \r\n terminating the old headers and the beginning of the message
561         // body. Both will be recovered later.
562         bytes_written = snprintf(eoh, XHEADERS_BUFSIZE,
563                         "X-Siptrace-Fromip: %.*s\r\n"
564                         "X-Siptrace-Toip: %.*s\r\n"
565                         "X-Siptrace-Time: %llu %llu\r\n"
566                         "X-Siptrace-Method: %.*s\r\n"
567                         "X-Siptrace-Dir: %s\r\n",
568                         sto->fromip.len, sto->fromip.s,
569                         sto->toip.len, sto->toip.s,
570                         (unsigned long long)sto->tv.tv_sec, (unsigned long long)sto->tv.tv_usec,
571                         sto->method.len, sto->method.s,
572                         sto->dir);
573         if (bytes_written >= XHEADERS_BUFSIZE) {
574                 LM_ERR("sip_trace_xheaders_write: string too long\n");
575                 goto error;
576         }
577
578         // Copy the \r\n terminating the old headers and the message body from the
579         // old buffer in sto->body.s to the new end-of-header in buf.
580         eoh_offset = eoh - buf;
581         new_eoh = eoh + bytes_written;
582         memcpy(new_eoh, sto->body.s + eoh_offset, sto->body.len - eoh_offset);
583
584         // Change sto to point to the new buffer.
585         sto->body.s = buf;
586         sto->body.len += bytes_written;
587         return 0;
588 error:
589         if(buf != NULL)
590                 pkg_free(buf);
591         return -1;
592 }
593
594 // Parses x-headers, saves the data back to sto, and removes the x-headers
595 // from the message in sto->buf
596 static int sip_trace_xheaders_read(struct _siptrace_data *sto)
597 {
598         char* searchend = NULL;
599         char* eoh = NULL;
600         char* xheaders = NULL;
601         long long unsigned int tv_sec, tv_usec;
602
603         if(xheaders_read_flag==NULL || *xheaders_read_flag==0)
604                 return 0;
605
606         // Find the end-of-header marker \r\n\r\n
607         searchend = sto->body.s + sto->body.len - 3;
608         eoh = memchr(sto->body.s, '\r', searchend - eoh);
609         while (eoh != NULL && eoh < searchend) {
610                 if (memcmp(eoh, "\r\n\r\n", 4) == 0)
611                         break;
612                 eoh = memchr(eoh + 1, '\r', searchend - eoh);
613         }
614         if (eoh == NULL) {
615                 LM_ERR("sip_trace_xheaders_read: malformed message\n");
616                 return -1;
617         }
618
619         // Find x-headers: eoh will be overwritten by \0 to allow the use of
620         // strstr(). The byte at eoh will later be recovered, when the
621         // message body is shifted towards the beginning of the message
622         // to remove the x-headers.
623         *eoh = '\0';
624         xheaders = strstr(sto->body.s, "\r\nX-Siptrace-Fromip: ");
625         if (xheaders == NULL) {
626                 LM_ERR("sip_trace_xheaders_read: message without x-headers "
627                                 "from %.*s, callid %.*s\n",
628                                 sto->fromip.len, sto->fromip.s, sto->callid.len, sto->callid.s);
629                 return -1;
630         }
631
632         // Allocate memory for new strings in sto
633         // (gets free()ed in sip_trace_xheaders_free() )
634         sto->fromip.s = pkg_malloc(51);
635         sto->toip.s = pkg_malloc(51);
636         sto->method.s = pkg_malloc(51);
637         sto->dir = pkg_malloc(4);
638         if (!(sto->fromip.s && sto->toip.s && sto->method.s && sto->dir)) {
639                 LM_ERR("sip_trace_xheaders_read: out of memory\n");
640                 goto erroraftermalloc;
641         }
642
643         // Parse the x-headers: scanf()
644         if (sscanf(xheaders, "\r\n"
645                                 "X-Siptrace-Fromip: %50s\r\n"
646                                 "X-Siptrace-Toip: %50s\r\n"
647                                 "X-Siptrace-Time: %llu %llu\r\n"
648                                 "X-Siptrace-Method: %50s\r\n"
649                                 "X-Siptrace-Dir: %3s",
650                                 sto->fromip.s, sto->toip.s,
651                                 &tv_sec, &tv_usec,
652                                 sto->method.s,
653                                 sto->dir) == EOF) {
654                 LM_ERR("sip_trace_xheaders_read: malformed x-headers\n");
655                 goto erroraftermalloc;
656         }
657         sto->fromip.len = strlen(sto->fromip.s);
658         sto->toip.len = strlen(sto->toip.s);
659         sto->tv.tv_sec = (time_t)tv_sec;
660         sto->tv.tv_usec = (suseconds_t)tv_usec;
661         sto->method.len = strlen(sto->method.s);
662
663         // Remove the x-headers: the message body is shifted towards the beginning
664         // of the message, overwriting the x-headers. Before that, the byte at eoh
665         // is recovered.
666         *eoh = '\r';
667         memmove(xheaders, eoh, sto->body.len - (eoh - sto->body.s));
668         sto->body.len -= eoh - xheaders;
669
670         return 0;
671
672 erroraftermalloc:
673         if (sto->fromip.s)
674                 pkg_free(sto->fromip.s);
675         if (sto->toip.s)
676                 pkg_free(sto->toip.s);
677         if (sto->method.s)
678                 pkg_free(sto->method.s);
679         if (sto->dir)
680                 pkg_free(sto->dir);
681         return -1;
682 }
683
684 // Frees the memory allocated by sip_trace_xheaders_{write,read}
685 static int sip_trace_xheaders_free(struct _siptrace_data *sto)
686 {
687         if (xheaders_write_flag != NULL && *xheaders_write_flag != 0) {
688                 if(sto->body.s)
689                         pkg_free(sto->body.s);
690         }
691
692         if (xheaders_read_flag != NULL && *xheaders_read_flag != 0) {
693                 if(sto->fromip.s)
694                         pkg_free(sto->fromip.s);
695                 if(sto->toip.s)
696                         pkg_free(sto->toip.s);
697                 if(sto->dir)
698                         pkg_free(sto->dir);
699         }
700
701         return 0;
702 }
703
704 static int sip_trace_store(struct _siptrace_data *sto)
705 {
706         if(sto==NULL)
707         {
708                 LM_DBG("invalid parameter\n");
709                 return -1;
710         }
711
712         gettimeofday(&sto->tv, NULL);
713
714         if (sip_trace_xheaders_read(sto) != 0)
715                 return -1;
716         int ret = sip_trace_store_db(sto);
717
718         if (sip_trace_xheaders_write(sto) != 0)
719                 return -1;
720
721         if(hep_mode_on) trace_send_hep_duplicate(&sto->body, &sto->fromip, &sto->toip);
722         else trace_send_duplicate(sto->body.s, sto->body.len);
723
724         if (sip_trace_xheaders_free(sto) != 0)
725                 return -1;
726
727         return ret;
728 }
729
730 static int sip_trace_store_db(struct _siptrace_data *sto)
731 {
732         if(trace_to_database_flag==NULL || *trace_to_database_flag==0)
733                 goto done;
734
735         db_key_t db_keys[NR_KEYS];
736         db_val_t db_vals[NR_KEYS];
737
738         db_keys[0] = &msg_column;
739         db_vals[0].type = DB1_BLOB;
740         db_vals[0].nul = 0;
741         db_vals[0].val.blob_val = sto->body;
742
743         db_keys[1] = &callid_column;
744         db_vals[1].type = DB1_STR;
745         db_vals[1].nul = 0;
746         db_vals[1].val.str_val = sto->callid;
747
748         db_keys[2] = &method_column;
749         db_vals[2].type = DB1_STR;
750         db_vals[2].nul = 0;
751         db_vals[2].val.str_val = sto->method;
752
753         db_keys[3] = &status_column;
754         db_vals[3].type = DB1_STR;
755         db_vals[3].nul = 0;
756         db_vals[3].val.str_val = sto->status;
757
758         db_keys[4] = &fromip_column;
759         db_vals[4].type = DB1_STR;
760         db_vals[4].nul = 0;
761         db_vals[4].val.str_val = sto->fromip;
762
763         db_keys[5] = &toip_column;
764         db_vals[5].type = DB1_STR;
765         db_vals[5].nul = 0;
766         db_vals[5].val.str_val = sto->toip;
767
768         db_keys[6] = &date_column;
769         db_vals[6].type = DB1_DATETIME;
770         db_vals[6].nul = 0;
771         db_vals[6].val.time_val = sto->tv.tv_sec;
772
773         db_keys[7] = &direction_column;
774         db_vals[7].type = DB1_STRING;
775         db_vals[7].nul = 0;
776         db_vals[7].val.string_val = sto->dir;
777
778         db_keys[8] = &fromtag_column;
779         db_vals[8].type = DB1_STR;
780         db_vals[8].nul = 0;
781         db_vals[8].val.str_val = sto->fromtag;
782
783         db_keys[9] = &traced_user_column;
784         db_vals[9].type = DB1_STR;
785         db_vals[9].nul = 0;
786
787         db_keys[10] = &time_us_column;
788         db_vals[10].type = DB1_INT;
789         db_vals[10].nul = 0;
790         db_vals[10].val.int_val = sto->tv.tv_usec;
791
792         db_funcs.use_table(db_con, siptrace_get_table());
793
794         if(trace_on_flag!=NULL && *trace_on_flag!=0) {
795                 db_vals[9].val.str_val.s   = "";
796                 db_vals[9].val.str_val.len = 0;
797
798                 LM_DBG("storing info...\n");
799                 if(trace_delayed!=0 && db_funcs.insert_delayed!=NULL)
800                 {
801                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS)<0) {
802                                 LM_ERR("error storing trace\n");
803                                 goto error;
804                         }
805                 } else {
806                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
807                                 LM_ERR("error storing trace\n");
808                                 goto error;
809                         }
810                 }
811 #ifdef STATISTICS
812                 update_stat(sto->stat, 1);
813 #endif
814         }
815
816         if(sto->avp==NULL)
817                 goto done;
818
819         db_vals[9].val.str_val = sto->avp_value.s;
820
821         LM_DBG("storing info...\n");
822         if(trace_delayed!=0 && db_funcs.insert_delayed!=NULL)
823         {
824                 if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
825                         LM_ERR("error storing trace\n");
826                         goto error;
827                 }
828         } else {
829                 if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
830                         LM_ERR("error storing trace\n");
831                         goto error;
832                 }
833         }
834
835         sto->avp = search_next_avp(&sto->state, &sto->avp_value);
836         while(sto->avp!=NULL) {
837                 db_vals[9].val.str_val = sto->avp_value.s;
838
839                 LM_DBG("storing info...\n");
840                 if(trace_delayed!=0 && db_funcs.insert_delayed!=NULL)
841                 {
842                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
843                                 LM_ERR("error storing trace\n");
844                                 goto error;
845                         }
846                 } else {
847                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
848                                 LM_ERR("error storing trace\n");
849                                 goto error;
850                         }
851                 }
852                 sto->avp = search_next_avp(&sto->state, &sto->avp_value);
853         }
854
855 done:
856         return 1;
857 error:
858         return -1;
859 }
860
861 static int sip_trace(struct sip_msg *msg, char *dir, char *s2)
862 {
863         struct _siptrace_data sto;
864         struct onsend_info *snd_inf = NULL;
865
866         if(msg==NULL) {
867                 LM_DBG("nothing to trace\n");
868                 return -1;
869         }
870         memset(&sto, 0, sizeof(struct _siptrace_data));
871
872         if(traced_user_avp.n!=0)
873                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
874                                 &sto.avp_value, &sto.state);
875
876         if((sto.avp==NULL) && (trace_on_flag==NULL || *trace_on_flag==0)) {
877                 LM_DBG("trace off...\n");
878                 return -1;
879         }
880         if(sip_trace_prepare(msg)<0)
881                 return -1;
882
883         sto.callid = msg->callid->body;
884
885         if(msg->first_line.type==SIP_REQUEST) {
886                 sto.method = msg->first_line.u.request.method;
887         } else {
888                 if(parse_headers(msg, HDR_CSEQ_F, 0) != 0 || msg->cseq==NULL
889                                 || msg->cseq->parsed==NULL) {
890                         LM_ERR("cannot parse cseq header\n");
891                         return -1;
892                 }
893                 sto.method = get_cseq(msg)->method;
894         }
895
896         if(msg->first_line.type==SIP_REPLY) {
897                 sto.status = msg->first_line.u.reply.status;
898         } else {
899                 sto.status.s = "";
900                 sto.status.len = 0;
901         }
902
903         snd_inf=get_onsend_info();
904         if(snd_inf==NULL) {
905                 sto.body.s = msg->buf;
906                 sto.body.len = msg->len;
907
908                 siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
909                 strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.src_ip));
910                 strcat(sto.fromip_buff,":");
911                 strcat(sto.fromip_buff, int2str(msg->rcv.src_port, NULL));
912                 sto.fromip.s = sto.fromip_buff;
913                 sto.fromip.len = strlen(sto.fromip_buff);
914
915                 siptrace_copy_proto(msg->rcv.proto, sto.toip_buff);
916                 strcat(sto.toip_buff, ip_addr2a(&msg->rcv.dst_ip));
917                 strcat(sto.toip_buff,":");
918                 strcat(sto.toip_buff, int2str(msg->rcv.dst_port, NULL));
919                 sto.toip.s = sto.toip_buff;
920                 sto.toip.len = strlen(sto.toip_buff);
921
922                 sto.dir = (dir)?dir:"in";
923         } else {
924                 sto.body.s   = snd_inf->buf;
925                 sto.body.len = snd_inf->len;
926
927                 strncpy(sto.fromip_buff, snd_inf->send_sock->sock_str.s,
928                                 snd_inf->send_sock->sock_str.len);
929                 sto.fromip.s = sto.fromip_buff;
930                 sto.fromip.len = strlen(sto.fromip_buff);
931
932                 siptrace_copy_proto(snd_inf->send_sock->proto, sto.toip_buff);
933                 strcat(sto.toip_buff, suip2a(snd_inf->to, sizeof(*snd_inf->to)));
934                 strcat(sto.toip_buff,":");
935                 strcat(sto.toip_buff, int2str((int)su_getport(snd_inf->to), NULL));
936                 sto.toip.s = sto.toip_buff;
937                 sto.toip.len = strlen(sto.toip_buff);
938
939                 sto.dir = "out";
940         }
941
942         sto.fromtag = get_from(msg)->tag_value;
943
944 #ifdef STATISTICS
945         if(msg->first_line.type==SIP_REPLY) {
946                 sto.stat = siptrace_rpl;
947         } else {
948                 sto.stat = siptrace_req;
949         }
950 #endif
951         return sip_trace_store(&sto);
952 }
953
954 #define trace_is_off(_msg) \
955         (trace_on_flag==NULL || *trace_on_flag==0 || \
956          ((_msg)->flags&trace_flag)==0)
957
958 static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps)
959 {
960         struct sip_msg* msg;
961         int_str         avp_value;
962         struct usr_avp* avp;
963
964         if(t==NULL || ps==NULL)
965         {
966                 LM_DBG("no uas request, local transaction\n");
967                 return;
968         }
969
970         msg = ps->req;
971         if(msg==NULL)
972         {
973                 LM_DBG("no uas request, local transaction\n");
974                 return;
975         }
976
977         avp = NULL;
978         if(traced_user_avp.n!=0)
979                 avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value,
980                                 0);
981
982         if((avp==NULL) && trace_is_off(msg))
983         {
984                 LM_DBG("trace off...\n");
985                 return;
986         }
987
988         if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL)
989         {
990                 LM_ERR("cannot parse FROM header\n");
991                 return;
992         }
993
994         if(parse_headers(msg, HDR_CALLID_F, 0)!=0)
995         {
996                 LM_ERR("cannot parse call-id\n");
997                 return;
998         }
999
1000         if(tmb.register_tmcb(0, t, TMCB_REQUEST_SENT, trace_onreq_out, 0, 0) <=0)
1001         {
1002                 LM_ERR("can't register trace_onreq_out\n");
1003                 return;
1004         }
1005         if(tmb.register_tmcb(0, t, TMCB_RESPONSE_IN, trace_onreply_in, 0, 0) <=0)
1006         {
1007                 LM_ERR("can't register trace_onreply_in\n");
1008                 return;
1009         }
1010
1011         if(tmb.register_tmcb(0, t, TMCB_RESPONSE_SENT, trace_onreply_out, 0, 0)<=0)
1012         {
1013                 LM_ERR("can't register trace_onreply_out\n");
1014                 return;
1015         }
1016 }
1017
1018 static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps)
1019 {
1020         struct _siptrace_data sto;
1021         sip_msg_t *msg;
1022         struct ip_addr to_ip;
1023         int len;
1024         struct dest_info *dst;
1025
1026         if(t==NULL || ps==NULL) {
1027                 LM_DBG("very weird\n");
1028                 return;
1029         }
1030
1031         if(ps->flags&TMCB_RETR_F) {
1032                 LM_DBG("retransmission\n");
1033                 return;
1034         }
1035         msg=ps->req;
1036         if(msg==NULL) {
1037                 /* check if it is outgoing cancel, t is INVITE
1038                  * and send_buf starts with CANCEL */
1039                 if(is_invite(t) && ps->send_buf.len>7
1040                                 && strncmp(ps->send_buf.s, "CANCEL ", 7)==0) {
1041                         msg = t->uas.request;
1042                         if(msg==NULL) {
1043                                 LM_DBG("no uas msg for INVITE transaction\n");
1044                                 return;
1045                         } else {
1046                                 LM_DBG("recording CANCEL based on INVITE transaction\n");
1047                         }
1048                 } else {
1049                         LM_DBG("no uas msg, local transaction\n");
1050                         return;
1051                 }
1052         }
1053         memset(&sto, 0, sizeof(struct _siptrace_data));
1054
1055         if(traced_user_avp.n!=0)
1056                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
1057                                 &sto.avp_value, &sto.state);
1058
1059         if((sto.avp==NULL) && trace_is_off(msg) ) {
1060                 LM_DBG("trace off...\n");
1061                 return;
1062         }
1063
1064         if(sip_trace_prepare(msg)<0)
1065                 return;
1066
1067         if(ps->send_buf.len>0) {
1068                 sto.body = ps->send_buf;
1069         } else {
1070                 sto.body.s   = "No request buffer";
1071                 sto.body.len = sizeof("No request buffer")-1;
1072         }
1073
1074         sto.callid = msg->callid->body;
1075
1076         if(ps->send_buf.len>10) {
1077                 sto.method.s = ps->send_buf.s;
1078                 sto.method.len = 0;
1079                 while(sto.method.len<ps->send_buf.len) {
1080                         if(ps->send_buf.s[sto.method.len]==' ')
1081                                 break;
1082                         sto.method.len++;
1083                 }
1084                 if(sto.method.len==ps->send_buf.len)
1085                         sto.method.len = 10;
1086         } else {
1087                 sto.method = t->method;
1088         }
1089
1090         sto.status.s = "";
1091         sto.status.len = 0;
1092
1093         memset(&to_ip, 0, sizeof(struct ip_addr));
1094         dst = ps->dst;
1095
1096         if (trace_local_ip.s && trace_local_ip.len > 0) {
1097                 sto.fromip = trace_local_ip;
1098         } else {
1099                 if(dst==0 || dst->send_sock==0 || dst->send_sock->sock_str.s==0) {
1100                         siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
1101                         strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.dst_ip));
1102                         strcat(sto.fromip_buff,":");
1103                         strcat(sto.fromip_buff, int2str(msg->rcv.dst_port, NULL));
1104                         sto.fromip.s = sto.fromip_buff;
1105                         sto.fromip.len = strlen(sto.fromip_buff);
1106                 } else {
1107                         sto.fromip = dst->send_sock->sock_str;
1108                 }
1109         }
1110
1111         if(dst==0) {
1112                 sto.toip.s = "any:255.255.255.255";
1113                 sto.toip.len = 19;
1114         } else {
1115                 su2ip_addr(&to_ip, &dst->to);
1116                 siptrace_copy_proto(dst->proto, sto.toip_buff);
1117                 strcat(sto.toip_buff, ip_addr2a(&to_ip));
1118                 strcat(sto.toip_buff, ":");
1119                 strcat(sto.toip_buff,
1120                                 int2str((unsigned long)su_getport(&dst->to), &len));
1121                 sto.toip.s = sto.toip_buff;
1122                 sto.toip.len = strlen(sto.toip_buff);
1123         }
1124
1125         sto.dir = "out";
1126
1127         sto.fromtag = get_from(msg)->tag_value;
1128
1129 #ifdef STATISTICS
1130         sto.stat = siptrace_req;
1131 #endif
1132
1133         sip_trace_store(&sto);
1134         return;
1135 }
1136
1137 static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps)
1138 {
1139         struct _siptrace_data sto;
1140         sip_msg_t *msg;
1141         sip_msg_t *req;
1142         char statusbuf[8];
1143
1144         if(t==NULL || t->uas.request==0 || ps==NULL) {
1145                 LM_DBG("no uas request, local transaction\n");
1146                 return;
1147         }
1148
1149         req = ps->req;
1150         msg = ps->rpl;
1151         if(msg==NULL || req==NULL) {
1152                 LM_DBG("no reply\n");
1153                 return;
1154         }
1155         memset(&sto, 0, sizeof(struct _siptrace_data));
1156
1157         if(traced_user_avp.n!=0)
1158                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
1159                                 &sto.avp_value, &sto.state);
1160
1161         if((sto.avp==NULL) &&  trace_is_off(req)) {
1162                 LM_DBG("trace off...\n");
1163                 return;
1164         }
1165
1166         if(sip_trace_prepare(msg)<0)
1167                 return;
1168
1169         sto.body.s = msg->buf;
1170         sto.body.len = msg->len;
1171
1172         sto.callid = msg->callid->body;
1173
1174         sto.method = t->method;
1175
1176         strcpy(statusbuf, int2str(ps->code, &sto.status.len));
1177         sto.status.s = statusbuf;
1178
1179         siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
1180         strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.src_ip));
1181         strcat(sto.fromip_buff,":");
1182         strcat(sto.fromip_buff, int2str(msg->rcv.src_port, NULL));
1183         sto.fromip.s = sto.fromip_buff;
1184         sto.fromip.len = strlen(sto.fromip_buff);
1185
1186         if(trace_local_ip.s && trace_local_ip.len > 0) {
1187                 sto.toip = trace_local_ip;
1188         } else {
1189                 siptrace_copy_proto(msg->rcv.proto, sto.toip_buff);
1190                 strcat(sto.toip_buff, ip_addr2a(&msg->rcv.dst_ip));
1191                 strcat(sto.toip_buff,":");
1192                 strcat(sto.toip_buff, int2str(msg->rcv.dst_port, NULL));
1193                 sto.toip.s = sto.toip_buff;
1194                 sto.toip.len = strlen(sto.toip_buff);
1195         }
1196
1197         sto.dir = "in";
1198
1199         sto.fromtag = get_from(msg)->tag_value;
1200 #ifdef STATISTICS
1201         sto.stat = siptrace_rpl;
1202 #endif
1203
1204         sip_trace_store(&sto);
1205         return;
1206 }
1207
1208 static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps)
1209 {
1210         struct _siptrace_data sto;
1211         int faked = 0;
1212         struct sip_msg* msg;
1213         struct sip_msg* req;
1214         struct ip_addr to_ip;
1215         int len;
1216         char statusbuf[8];
1217         struct dest_info *dst;
1218
1219         if (t==NULL || t->uas.request==0 || ps==NULL) {
1220                 LM_DBG("no uas request, local transaction\n");
1221                 return;
1222         }
1223
1224         if(ps->flags&TMCB_RETR_F) {
1225                 LM_DBG("retransmission\n");
1226                 return;
1227         }
1228         memset(&sto, 0, sizeof(struct _siptrace_data));
1229         if(traced_user_avp.n!=0)
1230                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
1231                                 &sto.avp_value, &sto.state);
1232
1233         if((sto.avp==NULL) &&  trace_is_off(t->uas.request)) {
1234                 LM_DBG("trace off...\n");
1235                 return;
1236         }
1237
1238         req = ps->req;
1239         msg = ps->rpl;
1240         if(msg==NULL || msg==FAKED_REPLY) {
1241                 msg = t->uas.request;
1242                 faked = 1;
1243         }
1244
1245         if(sip_trace_prepare(msg)<0)
1246                 return;
1247
1248         if(faked==0) {
1249                 if(ps->send_buf.len>0) {
1250                         sto.body = ps->send_buf;
1251                 } else if(t->uas.response.buffer!=NULL) {
1252                         sto.body.s = t->uas.response.buffer;
1253                         sto.body.len = t->uas.response.buffer_len;
1254                 } else if(msg->len>0) {
1255                         sto.body.s = msg->buf;
1256                         sto.body.len = msg->len;
1257                 } else {
1258                         sto.body.s = "No reply buffer";
1259                         sto.body.len = sizeof("No reply buffer")-1;
1260                 }
1261         } else {
1262                 if(ps->send_buf.len>0) {
1263                         sto.body = ps->send_buf;
1264                 } else if(t->uas.response.buffer!=NULL) {
1265                         sto.body.s = t->uas.response.buffer;
1266                         sto.body.len = t->uas.response.buffer_len;
1267                 } else {
1268                         sto.body.s = "No reply buffer";
1269                         sto.body.len = sizeof("No reply buffer")-1;
1270                 }
1271         }
1272
1273         sto.callid = msg->callid->body;
1274         sto.method = t->method;
1275
1276         if(trace_local_ip.s && trace_local_ip.len > 0) {
1277                 sto.fromip = trace_local_ip;
1278         } else {
1279                 siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
1280                 strcat(sto.fromip_buff, ip_addr2a(&req->rcv.dst_ip));
1281                 strcat(sto.fromip_buff,":");
1282                 strcat(sto.fromip_buff, int2str(req->rcv.dst_port, NULL));
1283                 sto.fromip.s = sto.fromip_buff;
1284                 sto.fromip.len = strlen(sto.fromip_buff);
1285         }
1286
1287         strcpy(statusbuf, int2str(ps->code, &sto.status.len));
1288         sto.status.s = statusbuf;
1289
1290         memset(&to_ip, 0, sizeof(struct ip_addr));
1291         dst = ps->dst;
1292         if(dst==0) {
1293                 sto.toip.s = "any:255.255.255.255";
1294                 sto.toip.len = 19;
1295         } else {
1296                 su2ip_addr(&to_ip, &dst->to);
1297                 siptrace_copy_proto(dst->proto, sto.toip_buff);
1298                 strcat(sto.toip_buff, ip_addr2a(&to_ip));
1299                 strcat(sto.toip_buff, ":");
1300                 strcat(sto.toip_buff,
1301                                 int2str((unsigned long)su_getport(&dst->to), &len));
1302                 sto.toip.s = sto.toip_buff;
1303                 sto.toip.len = strlen(sto.toip_buff);
1304         }
1305
1306         sto.dir = "out";
1307         sto.fromtag = get_from(msg)->tag_value;
1308
1309 #ifdef STATISTICS
1310         sto.stat = siptrace_rpl;
1311 #endif
1312
1313         sip_trace_store(&sto);
1314         return;
1315 }
1316
1317 static void trace_sl_ack_in(sl_cbp_t *slcbp)
1318 {
1319         sip_msg_t *req;
1320         LM_DBG("storing ack...\n");
1321         req = slcbp->req;
1322         sip_trace(req, 0, 0);
1323 }
1324
1325 static void trace_sl_onreply_out(sl_cbp_t *slcbp)
1326 {
1327         sip_msg_t *req;
1328         struct _siptrace_data sto;
1329         struct sip_msg* msg;
1330         struct ip_addr to_ip;
1331         int len;
1332         char statusbuf[5];
1333
1334         if(slcbp==NULL || slcbp->req==NULL)
1335         {
1336                 LM_ERR("bad parameters\n");
1337                 return;
1338         }
1339         req = slcbp->req;
1340
1341         memset(&sto, 0, sizeof(struct _siptrace_data));
1342         if(traced_user_avp.n!=0)
1343                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
1344                                 &sto.avp_value, &sto.state);
1345
1346         if((sto.avp==NULL) && trace_is_off(req)) {
1347                 LM_DBG("trace off...\n");
1348                 return;
1349         }
1350
1351         msg = req;
1352
1353         if(sip_trace_prepare(msg)<0)
1354                 return;
1355
1356         sto.body.s = (slcbp->reply)?slcbp->reply->s:"";
1357         sto.body.len = (slcbp->reply)?slcbp->reply->len:0;
1358
1359         sto.callid = msg->callid->body;
1360         sto.method = msg->first_line.u.request.method;
1361
1362         if(trace_local_ip.len > 0) {
1363                 sto.fromip = trace_local_ip;
1364         } else {
1365                 siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
1366                 strcat(sto.fromip_buff, ip_addr2a(&req->rcv.dst_ip));
1367                 strcat(sto.fromip_buff,":");
1368                 strcat(sto.fromip_buff, int2str(req->rcv.dst_port, NULL));
1369                 sto.fromip.s = sto.fromip_buff;
1370                 sto.fromip.len = strlen(sto.fromip_buff);
1371         }
1372
1373         strcpy(statusbuf, int2str(slcbp->code, &sto.status.len));
1374         sto.status.s = statusbuf;
1375
1376         memset(&to_ip, 0, sizeof(struct ip_addr));
1377         if(slcbp->dst==0)
1378         {
1379                 sto.toip.s = "any:255.255.255.255";
1380                 sto.toip.len = 19;
1381         } else {
1382                 su2ip_addr(&to_ip, &slcbp->dst->to);
1383                 siptrace_copy_proto(req->rcv.proto, sto.toip_buff);
1384                 strcat(sto.toip_buff, ip_addr2a(&to_ip));
1385                 strcat(sto.toip_buff, ":");
1386                 strcat(sto.toip_buff,
1387                                 int2str((unsigned long)su_getport(&slcbp->dst->to), &len));
1388                 sto.toip.s = sto.toip_buff;
1389                 sto.toip.len = strlen(sto.toip_buff);
1390         }
1391
1392         sto.dir = "out";
1393         sto.fromtag = get_from(msg)->tag_value;
1394
1395 #ifdef STATISTICS
1396         sto.stat = siptrace_rpl;
1397 #endif
1398
1399         sip_trace_store(&sto);
1400         return;
1401 }
1402
1403
1404 /*! \brief
1405  * MI Sip_trace command
1406  *
1407  * MI command format:
1408  * name: sip_trace
1409  * attribute: name=none, value=[on|off]
1410  */
1411 static struct mi_root* sip_trace_mi(struct mi_root* cmd_tree, void* param )
1412 {
1413         struct mi_node* node;
1414
1415         struct mi_node *rpl; 
1416         struct mi_root *rpl_tree ; 
1417
1418         node = cmd_tree->node.kids;
1419         if(node == NULL) {
1420                 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
1421                 if (rpl_tree == 0)
1422                         return 0;
1423                 rpl = &rpl_tree->node;
1424
1425                 if (*trace_on_flag == 0 ) {
1426                         node = add_mi_node_child(rpl,0,0,0,MI_SSTR("off"));
1427                 } else if (*trace_on_flag == 1) {
1428                         node = add_mi_node_child(rpl,0,0,0,MI_SSTR("on"));
1429                 }
1430                 return rpl_tree ;
1431         }
1432         if(trace_on_flag==NULL)
1433                 return init_mi_tree( 500, MI_SSTR(MI_INTERNAL_ERR));
1434
1435         if ( node->value.len==2 && (node->value.s[0]=='o'
1436                                 || node->value.s[0]=='O') &&
1437                         (node->value.s[1]=='n'|| node->value.s[1]=='N')) {
1438                 *trace_on_flag = 1;
1439                 return init_mi_tree( 200, MI_SSTR(MI_OK));
1440         } else if ( node->value.len==3 && (node->value.s[0]=='o'
1441                                 || node->value.s[0]=='O')
1442                         && (node->value.s[1]=='f'|| node->value.s[1]=='F')
1443                         && (node->value.s[2]=='f'|| node->value.s[2]=='F')) {
1444                 *trace_on_flag = 0;
1445                 return init_mi_tree( 200, MI_SSTR(MI_OK));
1446         } else {
1447                 return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
1448         }
1449 }
1450
1451 static int trace_send_duplicate(char *buf, int len)
1452 {
1453         struct dest_info dst;
1454         struct proxy_l * p;
1455
1456         if(buf==NULL || len <= 0)
1457                 return -1;
1458
1459         if(dup_uri_str.s==0 || dup_uri==NULL)
1460                 return 0;
1461
1462         init_dest_info(&dst);
1463         /* create a temporary proxy*/
1464         dst.proto = PROTO_UDP;
1465         p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,
1466                         dst.proto);
1467         if (p==0)
1468         {
1469                 LM_ERR("bad host name in uri\n");
1470                 return -1;
1471         }
1472
1473         hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
1474
1475         dst.send_sock=get_send_socket(0, &dst.to, dst.proto);
1476         if (dst.send_sock==0)
1477         {
1478                 LM_ERR("can't forward to af %d, proto %d no corresponding"
1479                                 " listening socket\n", dst.to.s.sa_family, dst.proto);
1480                 goto error;
1481         }
1482
1483         if (msg_send(&dst, buf, len)<0)
1484         {
1485                 LM_ERR("cannot send duplicate message\n");
1486                 goto error;
1487         }
1488
1489         free_proxy(p); /* frees only p content, not p itself */
1490         pkg_free(p);
1491         return 0;
1492 error:
1493         free_proxy(p); /* frees only p content, not p itself */
1494         pkg_free(p);
1495         return -1;
1496 }
1497
1498 static int trace_send_hep_duplicate(str *body, str *from, str *to)
1499 {
1500         struct dest_info dst;
1501         struct proxy_l * p=NULL /* make gcc happy */;
1502         void* buffer = NULL;
1503         union sockaddr_union from_su;
1504         union sockaddr_union to_su;
1505         unsigned int len, buflen, proto;
1506         struct hep_hdr hdr;
1507         struct hep_iphdr hep_ipheader;
1508         struct hep_timehdr hep_time;
1509         struct timeval tvb;
1510         struct timezone tz;
1511                          
1512 #if USE_IPV6
1513         struct hep_ip6hdr hep_ip6header;
1514 #endif
1515
1516         if(body->s==NULL || body->len <= 0)
1517                 return -1;
1518
1519         if(dup_uri_str.s==0 || dup_uri==NULL)
1520                 return 0;
1521
1522
1523         gettimeofday( &tvb, &tz );
1524         
1525
1526         /* message length */
1527         len = body->len 
1528 #if USE_IPV6
1529                 + sizeof(struct hep_ip6hdr)
1530 #else
1531                 + sizeof(struct hep_iphdr)          
1532 #endif
1533                 + sizeof(struct hep_hdr) + sizeof(struct hep_timehdr);;
1534
1535
1536         /* The packet is too big for us */
1537         if (unlikely(len>BUF_SIZE)){
1538                 goto error;
1539         }
1540
1541         /* Convert proto:ip:port to sockaddress union SRC IP */
1542         if (pipport2su(from->s, &from_su, &proto)==-1 || (pipport2su(to->s, &to_su, &proto)==-1))
1543                 goto error;
1544
1545         /* check if from and to are in the same family*/
1546         if(from_su.s.sa_family != to_su.s.sa_family) {
1547                 LOG(L_ERR, "ERROR: trace_send_hep_duplicate: interworking detected ?\n");
1548                 goto error;
1549         }
1550
1551         init_dest_info(&dst);
1552         /* create a temporary proxy*/
1553         dst.proto = PROTO_UDP;
1554         p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,
1555                         dst.proto);
1556         if (p==0)
1557         {
1558                 LM_ERR("bad host name in uri\n");
1559                 goto error;
1560         }
1561
1562         hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
1563
1564         dst.send_sock=get_send_socket(0, &dst.to, dst.proto);
1565         if (dst.send_sock==0)
1566         {
1567                 LM_ERR("can't forward to af %d, proto %d no corresponding"
1568                                 " listening socket\n", dst.to.s.sa_family, dst.proto);
1569                 goto error;
1570         }
1571
1572         /* Version && proto && length */
1573         hdr.hp_l = sizeof(struct hep_hdr);
1574         hdr.hp_v = hep_version;
1575         hdr.hp_p = proto;
1576
1577         /* AND the last */
1578         if (from_su.s.sa_family==AF_INET){
1579                 /* prepare the hep headers */
1580
1581                 hdr.hp_f = AF_INET;
1582                 hdr.hp_sport = htons(from_su.sin.sin_port);
1583                 hdr.hp_dport = htons(to_su.sin.sin_port);
1584
1585                 hep_ipheader.hp_src = from_su.sin.sin_addr;
1586                 hep_ipheader.hp_dst = to_su.sin.sin_addr;
1587
1588                 len = sizeof(struct hep_iphdr);
1589         }
1590 #ifdef USE_IPV6
1591         else if (from_su.s.sa_family==AF_INET6){
1592                 /* prepare the hep6 headers */
1593
1594                 hdr.hp_f = AF_INET6;
1595
1596                 hdr.hp_sport = htons(from_su.sin6.sin6_port);
1597                 hdr.hp_dport = htons(to_su.sin6.sin6_port);
1598
1599                 hep_ip6header.hp6_src = from_su.sin6.sin6_addr;
1600                 hep_ip6header.hp6_dst = to_su.sin6.sin6_addr;
1601
1602                 len = sizeof(struct hep_ip6hdr);
1603         }
1604 #endif /* USE_IPV6 */
1605         else {
1606                 LOG(L_ERR, "ERROR: trace_send_hep_duplicate: Unsupported protocol family\n");
1607                 goto error;;
1608         }
1609
1610         hdr.hp_l +=len;
1611         len += sizeof(struct hep_hdr) + body->len;
1612         buffer = (void *)pkg_malloc(len+1);
1613         if (buffer==0){
1614                 LOG(L_ERR, "ERROR: trace_send_hep_duplicate: out of memory\n");
1615                 goto error;
1616         }
1617
1618         /* Copy job */
1619         memset(buffer, '\0', len+1);
1620
1621         /* copy hep_hdr */
1622         memcpy((void*)buffer, &hdr, sizeof(struct hep_hdr));
1623         buflen = sizeof(struct hep_hdr);
1624
1625         /* hep_ip_hdr */
1626         if(from_su.s.sa_family==AF_INET) {
1627                 memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
1628                 buflen += sizeof(struct hep_iphdr);
1629         }
1630 #if USE_IPV6
1631         else {
1632                 memcpy((void*)buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
1633                 buflen += sizeof(struct hep_ip6hdr);
1634         }
1635 #endif /* USE_IPV6 */
1636
1637         if(hep_version == 2) {
1638
1639                 hep_time.tv_sec = tvb.tv_sec;
1640                 hep_time.tv_usec = tvb.tv_usec;
1641                 hep_time.captid = hep_capture_id;
1642
1643                 memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr));
1644                 buflen += sizeof(struct hep_timehdr);
1645         }
1646
1647         /* PAYLOAD */
1648         memcpy((void*)(buffer + buflen) , (void*)body->s, body->len);
1649         buflen +=body->len;
1650
1651         if (msg_send(&dst, buffer, buflen)<0)
1652         {
1653                 LM_ERR("cannot send hep duplicate message\n");
1654                 goto error;
1655         }
1656
1657         free_proxy(p); /* frees only p content, not p itself */
1658         pkg_free(p);
1659         pkg_free(buffer);
1660         return 0;
1661 error:
1662         if(p)
1663         {
1664                 free_proxy(p); /* frees only p content, not p itself */
1665                 pkg_free(p);
1666         }
1667         if(buffer) pkg_free(buffer);
1668         return -1;
1669 }
1670
1671 /*!
1672  * \brief Convert a STR [proto:]ip[:port] into socket address.
1673  * [proto:]ip[:port]
1674  * \param pipport (udp:127.0.0.1:5060 or tcp:2001:0DB8:AC10:FE01:5060)
1675  * \param tmp_su target structure
1676  * \param proto uint protocol type
1677  * \return success / unsuccess
1678  */
1679 static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto)
1680 {
1681         unsigned int port_no, cutlen = 4;
1682         struct ip_addr *ip;
1683         char *p, *host_s;
1684         str port_str, host_uri;
1685         unsigned len = 0;
1686         char tmp_piport[256];
1687
1688         /*parse protocol */
1689         if(strncmp(pipport, "udp:",4) == 0) *proto = IPPROTO_UDP;
1690         else if(strncmp(pipport, "tcp:",4) == 0) *proto = IPPROTO_TCP;
1691         else if(strncmp(pipport, "tls:",4) == 0) *proto = IPPROTO_IDP; /* fake proto type */
1692 #ifdef USE_SCTP
1693         else if(strncmp(pipport, "sctp:",5) == 0) cutlen = 5, *proto = IPPROTO_SCTP;
1694 #endif
1695         else if(strncmp(pipport, "any:",4) == 0) *proto = IPPROTO_UDP;
1696         else {
1697                 LM_ERR("bad protocol %s\n", pipport);
1698                 return -1;
1699         }
1700         
1701         if((len = strlen(pipport)) >= 256) {
1702                 LM_ERR("too big pipport\n");
1703                 goto error;
1704         }
1705
1706         /* our tmp string */
1707         strncpy(tmp_piport, pipport, len+1);
1708
1709         len = 0;
1710
1711         /*separate proto and host */
1712         p = tmp_piport+cutlen;
1713         if( (*(p)) == '\0') {
1714                 LM_ERR("malformed ip address\n");
1715                 goto error;
1716         }
1717         host_s=p;
1718
1719         if( (p = strrchr(p+1, ':')) == 0 ) {
1720                 LM_DBG("no port specified\n");
1721                 port_no = 0;
1722         }
1723         else {
1724                 /*the address contains a port number*/
1725                 *p = '\0';
1726                 p++;
1727                 port_str.s = p;
1728                 port_str.len = strlen(p);
1729                 LM_DBG("the port string is %s\n", p);
1730                 if(str2int(&port_str, &port_no) != 0 ) {
1731                         LM_ERR("there is not a valid number port\n");
1732                         goto error;
1733                 }
1734                 *p = '\0';
1735         }
1736         
1737         /* now IPv6 address has no brakets. It should be fixed! */
1738         if (host_s[0] == '[') {
1739                 len = strlen(host_s + 1) - 1;
1740                 if(host_s[len+1] != ']') {
1741                         LM_ERR("bracket not closed\n");
1742                         goto error;
1743                 }
1744                 memmove(host_s, host_s + 1, len);
1745                 host_s[len] = '\0';
1746         }
1747
1748         host_uri.s = host_s;
1749         host_uri.len = strlen(host_s);
1750
1751         /* check if it's an ip address */
1752         if (((ip=str2ip(&host_uri))!=0)
1753 #ifdef  USE_IPV6
1754                         || ((ip=str2ip6(&host_uri))!=0)
1755 #endif
1756            ) {
1757                 ip_addr2su(tmp_su, ip, ntohs(port_no));
1758                 return 0;       
1759
1760         }
1761
1762 error:
1763         return -1;
1764 }