siptrace.c

Go to the documentation of this file.
00001 /* 
00002  * $Id$ 
00003  *
00004  * siptrace module - helper module to trace sip messages
00005  *
00006  * Copyright (C) 2006 Voice Sistem S.R.L.
00007  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
00008  *
00009  * This file is part of Kamailio, a free SIP server.
00010  *
00011  * Kamailio is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * Kamailio is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License 
00022  * along with this program; if not, write to the Free Software 
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  */
00026 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <time.h>
00037 #include "../../sr_module.h"
00038 #include "../../dprint.h"
00039 #include "../../ut.h"
00040 #include "../../ip_addr.h"
00041 #include "../../mem/mem.h"
00042 #include "../../mem/shm_mem.h"
00043 #include "../../lib/kmi/mi.h"
00044 #include "../../lib/srdb1/db.h"
00045 #include "../../parser/parse_content.h"
00046 #include "../../parser/parse_from.h"
00047 #include "../../parser/parse_cseq.h"
00048 #include "../../pvar.h"
00049 #include "../../modules/tm/tm_load.h"
00050 #include "../../modules/sl/sl.h"
00051 #include "../../str.h"
00052 #include "../../onsend.h"
00053 
00054 #include "../../modules/sipcapture/sipcapture.h"
00055 
00056 #ifdef STATISTICS
00057 #include "../../lib/kcore/statistics.h"
00058 #endif
00059 
00060 MODULE_VERSION
00061 
00062 struct _siptrace_data {
00063         struct usr_avp *avp;
00064         int_str avp_value;
00065         struct search_state state;
00066         str body;
00067         str callid;
00068         str method;
00069         str status;
00070         char *dir;
00071         str fromtag;
00072         str fromip;
00073         str toip;
00074         char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
00075         char fromip_buff[IP_ADDR_MAX_STR_SIZE+12];
00076         struct timeval tv;
00077 #ifdef STATISTICS
00078         stat_var *stat;
00079 #endif
00080 };
00081 
00082 struct tm_binds tmb;
00083 
00085 sl_api_t slb;
00086 
00087 /* module function prototypes */
00088 static int mod_init(void);
00089 static int child_init(int rank);
00090 static void destroy(void);
00091 static int sip_trace(struct sip_msg*, char*, char*);
00092 
00093 static int sip_trace_store_db(struct _siptrace_data* sto);
00094 static int trace_send_duplicate(char *buf, int len);
00095 
00096 static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps);
00097 static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps);
00098 static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps);
00099 static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps);
00100 static void trace_sl_onreply_out(sl_cbp_t *slcb);
00101 static void trace_sl_ack_in(sl_cbp_t *slcb);
00102 
00103 static int trace_send_hep_duplicate(str *body, str *from, str *to);
00104 static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto);
00105 
00106 
00107 static struct mi_root* sip_trace_mi(struct mi_root* cmd, void* param );
00108 
00109 static str db_url             = str_init(DEFAULT_RODB_URL);
00110 static str siptrace_table     = str_init("sip_trace");
00111 static str date_column        = str_init("time_stamp");  /* 00 */
00112 static str callid_column      = str_init("callid");      /* 01 */
00113 static str traced_user_column = str_init("traced_user"); /* 02 */
00114 static str msg_column         = str_init("msg");         /* 03 */
00115 static str method_column      = str_init("method");      /* 04 */
00116 static str status_column      = str_init("status");      /* 05 */
00117 static str fromip_column      = str_init("fromip");      /* 06 */
00118 static str toip_column        = str_init("toip");        /* 07 */
00119 static str fromtag_column     = str_init("fromtag");     /* 08 */
00120 static str direction_column   = str_init("direction");   /* 09 */
00121 static str time_us_column     = str_init("time_us");     /* 10 */
00122 
00123 #define NR_KEYS 11
00124 
00125 #define XHEADERS_BUFSIZE 512
00126 
00127 int trace_flag = -1;
00128 int trace_on   = 0;
00129 int trace_sl_acks = 1;
00130 
00131 int trace_to_database = 1;
00132 int trace_delayed = 0;
00133 
00134 int hep_version = 1;
00135 int hep_capture_id = 1;
00136 
00137 int xheaders_write = 0;
00138 int xheaders_read = 0;
00139 
00140 str    dup_uri_str      = {0, 0};
00141 struct sip_uri *dup_uri = 0;
00142 
00143 int *trace_on_flag = NULL;
00144 int *trace_to_database_flag = NULL;
00145 
00146 int *xheaders_write_flag = NULL;
00147 int *xheaders_read_flag = NULL;
00148 
00149 static unsigned short traced_user_avp_type = 0;
00150 static int_str traced_user_avp;
00151 static str traced_user_avp_str = {NULL, 0};
00152 
00153 static unsigned short trace_table_avp_type = 0;
00154 static int_str trace_table_avp;
00155 static str trace_table_avp_str = {NULL, 0};
00156 
00157 static str trace_local_ip = {NULL, 0};
00158 
00159 int hep_mode_on = 0;
00160 
00161 db1_con_t *db_con = NULL;               
00162 db_func_t db_funcs;                     
00167 static cmd_export_t cmds[] = {
00168         {"sip_trace", (cmd_function)sip_trace, 0, 0, 0, ANY_ROUTE},
00169         {"sip_trace", (cmd_function)sip_trace, 1, 0, 0, ANY_ROUTE},
00170         {0, 0, 0, 0, 0, 0}
00171 };
00172 
00173 
00177 static param_export_t params[] = {
00178         {"db_url",             STR_PARAM, &db_url.s             },
00179         {"table",              STR_PARAM, &siptrace_table.s     },
00180         {"date_column",        STR_PARAM, &date_column.s        },
00181         {"callid_column",      STR_PARAM, &callid_column.s      },
00182         {"traced_user_column", STR_PARAM, &traced_user_column.s },
00183         {"msg_column",         STR_PARAM, &msg_column.s         },
00184         {"method_column",      STR_PARAM, &method_column.s      },
00185         {"status_column",      STR_PARAM, &status_column.s      },
00186         {"fromip_column",      STR_PARAM, &fromip_column.s      },
00187         {"toip_column",        STR_PARAM, &toip_column.s        },
00188         {"fromtag_column",     STR_PARAM, &fromtag_column.s     },
00189         {"direction_column",   STR_PARAM, &direction_column.s   },
00190         {"trace_flag",         INT_PARAM, &trace_flag           },
00191         {"trace_on",           INT_PARAM, &trace_on             },
00192         {"traced_user_avp",    STR_PARAM, &traced_user_avp_str.s},
00193         {"trace_table_avp",    STR_PARAM, &trace_table_avp_str.s},
00194         {"duplicate_uri",      STR_PARAM, &dup_uri_str.s        },
00195         {"trace_to_database",  INT_PARAM, &trace_to_database    },
00196         {"trace_local_ip",     STR_PARAM, &trace_local_ip.s     },
00197         {"trace_sl_acks",      INT_PARAM, &trace_sl_acks        },
00198         {"xheaders_write",     INT_PARAM, &xheaders_write       },
00199         {"xheaders_read",      INT_PARAM, &xheaders_read        },
00200         {"hep_mode_on",        INT_PARAM, &hep_mode_on          },       
00201         {"hep_version",        INT_PARAM, &hep_version          },
00202         {"hep_capture_id",     INT_PARAM, &hep_capture_id       },              
00203         {"trace_delayed",      INT_PARAM, &trace_delayed        },
00204         {0, 0, 0}
00205 };
00206 
00210 static mi_export_t mi_cmds[] = {
00211         { "sip_trace", sip_trace_mi,   0,  0,  0 },
00212         { 0, 0, 0, 0, 0}
00213 };
00214 
00215 
00216 #ifdef STATISTICS
00217 stat_var* siptrace_req;
00218 stat_var* siptrace_rpl;
00219 
00220 stat_export_t siptrace_stats[] = {
00221         {"traced_requests" ,  0,  &siptrace_req  },
00222         {"traced_replies"  ,  0,  &siptrace_rpl  },
00223         {0,0,0}
00224 };
00225 #endif
00226 
00228 struct module_exports exports = {
00229         "siptrace", 
00230         DEFAULT_DLFLAGS, 
00231         cmds,       
00232         params,     
00233 #ifdef STATISTICS
00234         siptrace_stats,  
00235 #else
00236         0,          
00237 #endif
00238         mi_cmds,    
00239         0,          
00240         0,          
00241         mod_init,   
00242         0,          
00243         destroy,    
00244         child_init  
00245 };
00246 
00247 
00249 static int mod_init(void)
00250 {
00251         pv_spec_t avp_spec;
00252         sl_cbelem_t slcb;
00253 
00254 #ifdef STATISTICS
00255         /* register statistics */
00256         if (register_module_stats(exports.name, siptrace_stats)!=0)
00257         {
00258                 LM_ERR("failed to register core statistics\n");
00259                 return -1;
00260         }
00261 #endif
00262 
00263         if(register_mi_mod(exports.name, mi_cmds)!=0)
00264         {
00265                 LM_ERR("failed to register MI commands\n");
00266                 return -1;
00267         }
00268 
00269         db_url.len = strlen(db_url.s);
00270         siptrace_table.len = strlen(siptrace_table.s);
00271         date_column.len = strlen(date_column.s);
00272         callid_column.len = strlen(callid_column.s);
00273         traced_user_column.len = strlen(traced_user_column.s);
00274         msg_column.len = strlen(msg_column.s);
00275         method_column.len = strlen(method_column.s);
00276         status_column.len = strlen(status_column.s);
00277         fromip_column.len = strlen(fromip_column.s);
00278         toip_column.len = strlen(toip_column.s);
00279         fromtag_column.len = strlen(fromtag_column.s);
00280         direction_column.len = strlen(direction_column.s);
00281         if (traced_user_avp_str.s)
00282                 traced_user_avp_str.len = strlen(traced_user_avp_str.s);
00283         if (trace_table_avp_str.s)
00284                 trace_table_avp_str.len = strlen(trace_table_avp_str.s);
00285         if (dup_uri_str.s)
00286                 dup_uri_str.len = strlen(dup_uri_str.s);
00287         if (trace_local_ip.s)
00288                 trace_local_ip.len = strlen(trace_local_ip.s);
00289 
00290         if (trace_flag<0 || trace_flag>(int)MAX_FLAG)
00291         {
00292                 LM_ERR("invalid trace flag %d\n", trace_flag);
00293                 return -1;
00294         }
00295         trace_flag = 1<<trace_flag;
00296 
00297         trace_to_database_flag = (int*)shm_malloc(sizeof(int));
00298         if(trace_to_database_flag==NULL) {
00299                 LM_ERR("no more shm memory left\n");
00300                 return -1;
00301         }
00302 
00303         *trace_to_database_flag = trace_to_database;
00304 
00305         /* Find a database module if needed */
00306         if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
00307                 if (db_bind_mod(&db_url, &db_funcs))
00308                 {
00309                         LM_ERR("unable to bind database module\n");
00310                         return -1;
00311                 }
00312                 if (trace_to_database_flag && !DB_CAPABILITY(db_funcs, DB_CAP_INSERT))
00313                 {
00314                         LM_ERR("database modules does not provide all functions needed"
00315                                         " by module\n");
00316                         return -1;
00317                 }
00318         }
00319 
00320         if(hep_version != 1 && hep_version != 2) {
00321   
00322                   LM_ERR("unsupported version of HEP");
00323                   return -1;
00324         }                                          
00325 
00326 
00327         trace_on_flag = (int*)shm_malloc(sizeof(int));
00328         if(trace_on_flag==NULL) {
00329                 LM_ERR("no more shm memory left\n");
00330                 return -1;
00331         }
00332 
00333         *trace_on_flag = trace_on;
00334 
00335         xheaders_write_flag = (int*)shm_malloc(sizeof(int));
00336         xheaders_read_flag = (int*)shm_malloc(sizeof(int));
00337         if (!(xheaders_write_flag && xheaders_read_flag)) {
00338                 LM_ERR("no more shm memory left\n");
00339                 return -1;
00340         }
00341         *xheaders_write_flag = xheaders_write;
00342         *xheaders_read_flag = xheaders_read;
00343 
00344         /* register callbacks to TM */
00345         if (load_tm_api(&tmb)!=0) {
00346                 LM_WARN("can't load tm api. Will not install tm callbacks.\n");
00347         } else if(tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, trace_onreq_in, 0, 0) <=0) {
00348                 LM_ERR("can't register trace_onreq_in\n");
00349                 return -1;
00350         }
00351 
00352         /* bind the SL API */
00353         if (sl_load_api(&slb)!=0) {
00354                 LM_WARN("cannot bind to SL API. Will not install sl callbacks.\n");
00355         } else {
00356                 /* register sl callbacks */
00357                 memset(&slcb, 0, sizeof(sl_cbelem_t));
00358 
00359                 slcb.type = SLCB_REPLY_READY;
00360                 slcb.cbf  = trace_sl_onreply_out;
00361                 if (slb.register_cb(&slcb) != 0) {
00362                         LM_ERR("can't register for SLCB_REPLY_READY\n");
00363                         return -1;
00364                 }
00365 
00366                 if(trace_sl_acks)
00367                 {
00368                         slcb.type = SLCB_ACK_FILTERED;
00369                         slcb.cbf  = trace_sl_ack_in;
00370                         if (slb.register_cb(&slcb) != 0) {
00371                                 LM_ERR("can't register for SLCB_ACK_FILTERED\n");
00372                                 return -1;
00373                         }
00374                 }
00375         }
00376 
00377         if(dup_uri_str.s!=0)
00378         {
00379                 dup_uri_str.len = strlen(dup_uri_str.s);
00380                 dup_uri = (struct sip_uri *)pkg_malloc(sizeof(struct sip_uri));
00381                 if(dup_uri==0)
00382                 {
00383                         LM_ERR("no more pkg memory left\n");
00384                         return -1;
00385                 }
00386                 memset(dup_uri, 0, sizeof(struct sip_uri));
00387                 if(parse_uri(dup_uri_str.s, dup_uri_str.len, dup_uri)<0)
00388                 {
00389                         LM_ERR("bad dup uri\n");
00390                         return -1;
00391                 }
00392         }
00393 
00394         if(traced_user_avp_str.s && traced_user_avp_str.len > 0)
00395         {
00396                 if (pv_parse_spec(&traced_user_avp_str, &avp_spec)==0
00397                                 || avp_spec.type!=PVT_AVP)
00398                 {
00399                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
00400                                         traced_user_avp_str.len, traced_user_avp_str.s);
00401                         return -1;
00402                 }
00403 
00404                 if(pv_get_avp_name(0, &avp_spec.pvp, &traced_user_avp,
00405                                         &traced_user_avp_type)!=0)
00406                 {
00407                         LM_ERR("[%.*s] - invalid AVP definition\n",
00408                                         traced_user_avp_str.len, traced_user_avp_str.s);
00409                         return -1;
00410                 }
00411         } else {
00412                 traced_user_avp.n = 0;
00413                 traced_user_avp_type = 0;
00414         }
00415         if(trace_table_avp_str.s && trace_table_avp_str.len > 0)
00416         {
00417                 if (pv_parse_spec(&trace_table_avp_str, &avp_spec)==0
00418                                 || avp_spec.type!=PVT_AVP)
00419                 {
00420                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
00421                                         trace_table_avp_str.len, trace_table_avp_str.s);
00422                         return -1;
00423                 }
00424 
00425                 if(pv_get_avp_name(0, &avp_spec.pvp, &trace_table_avp,
00426                                         &trace_table_avp_type)!=0)
00427                 {
00428                         LM_ERR("[%.*s] - invalid AVP definition\n",
00429                                         trace_table_avp_str.len, trace_table_avp_str.s);
00430                         return -1;
00431                 }
00432         } else {
00433                 trace_table_avp.n = 0;
00434                 trace_table_avp_type = 0;
00435         }
00436 
00437         return 0;
00438 }
00439 
00440 
00441 static int child_init(int rank)
00442 {
00443         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00444                 return 0; /* do nothing for the main process */
00445 
00446         if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
00447                 db_con = db_funcs.init(&db_url);
00448                 if (!db_con)
00449                 {
00450                         LM_ERR("unable to connect to database. Please check configuration.\n");
00451                         return -1;
00452                 }
00453         }
00454 
00455         return 0;
00456 }
00457 
00458 
00459 static void destroy(void)
00460 {
00461         if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
00462                 if (db_con!=NULL)
00463                         db_funcs.close(db_con);
00464         }
00465 
00466         if (trace_on_flag)
00467                 shm_free(trace_on_flag);
00468 
00469 }
00470 
00471 static inline int siptrace_copy_proto(int proto, char *buf)
00472 {
00473         if(buf==0)
00474                 return -1;
00475         if(proto==PROTO_TCP) {
00476                 strcpy(buf, "tcp:");
00477         } else if(proto==PROTO_TLS) {
00478                 strcpy(buf, "tls:");
00479         } else if(proto==PROTO_SCTP) {
00480                 strcpy(buf, "sctp:");
00481         } else {
00482                 strcpy(buf, "udp:");
00483         }
00484         return 0;
00485 }
00486 
00487 static inline str* siptrace_get_table(void)
00488 {
00489         static int_str         avp_value;
00490         struct usr_avp *avp;
00491 
00492         if(trace_table_avp.n==0)
00493                 return &siptrace_table;
00494 
00495         avp = NULL;
00496         if(trace_table_avp.n!=0)
00497                 avp=search_first_avp(trace_table_avp_type, trace_table_avp, &avp_value,
00498                                 0);
00499 
00500         if(avp==NULL || !is_avp_str_val(avp) || avp_value.s.len<=0)
00501                 return &siptrace_table;
00502 
00503         return &avp_value.s;
00504 }
00505 
00506 static int sip_trace_prepare(sip_msg_t *msg)
00507 {
00508         if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) {
00509                 LM_ERR("cannot parse FROM header\n");
00510                 goto error;
00511         }
00512 
00513         if(parse_headers(msg, HDR_CALLID_F, 0)!=0 || msg->callid==NULL
00514                         || msg->callid->body.s==NULL) {
00515                 LM_ERR("cannot parse call-id\n");
00516                 goto error;
00517         }
00518 
00519         return 0;
00520 error:
00521         return -1;
00522 }
00523 
00524 // Appends x-headers to the message in sto->body containing data from sto
00525 static int sip_trace_xheaders_write(struct _siptrace_data *sto)
00526 {
00527         char* buf = NULL;
00528         int bytes_written = 0;
00529         char* eoh = NULL;
00530         int eoh_offset = 0;
00531         char* new_eoh = NULL;
00532 
00533         if(xheaders_write_flag==NULL || *xheaders_write_flag==0)
00534                 return 0;
00535 
00536         // Memory for the message with some additional headers.
00537         // It gets free()ed in sip_trace_xheaders_free().
00538         buf = pkg_malloc(sto->body.len + XHEADERS_BUFSIZE);
00539         if (buf == NULL) {
00540                 LM_ERR("sip_trace_xheaders_write: out of memory\n");
00541                 return -1;
00542         }
00543 
00544         // Copy the whole message to buf first; it must be \0-terminated for
00545         // strstr() to work. Then search for the end-of-header sequence.
00546         memcpy(buf, sto->body.s, sto->body.len);
00547         buf[sto->body.len] = '\0';
00548         eoh = strstr(buf, "\r\n\r\n");
00549         if (eoh == NULL) {
00550                 LM_ERR("sip_trace_xheaders_write: malformed message\n");
00551                 goto error;
00552         }
00553         eoh += 2; // the first \r\n belongs to the last header => skip it
00554 
00555         // Write the new headers a the end-of-header position. This overwrites
00556         // the \r\n terminating the old headers and the beginning of the message
00557         // body. Both will be recovered later.
00558         bytes_written = snprintf(eoh, XHEADERS_BUFSIZE,
00559                         "X-Siptrace-Fromip: %.*s\r\n"
00560                         "X-Siptrace-Toip: %.*s\r\n"
00561                         "X-Siptrace-Time: %llu %llu\r\n"
00562                         "X-Siptrace-Method: %.*s\r\n"
00563                         "X-Siptrace-Dir: %s\r\n",
00564                         sto->fromip.len, sto->fromip.s,
00565                         sto->toip.len, sto->toip.s,
00566                         (unsigned long long)sto->tv.tv_sec, (unsigned long long)sto->tv.tv_usec,
00567                         sto->method.len, sto->method.s,
00568                         sto->dir);
00569         if (bytes_written >= XHEADERS_BUFSIZE) {
00570                 LM_ERR("sip_trace_xheaders_write: string too long\n");
00571                 goto error;
00572         }
00573 
00574         // Copy the \r\n terminating the old headers and the message body from the
00575         // old buffer in sto->body.s to the new end-of-header in buf.
00576         eoh_offset = eoh - buf;
00577         new_eoh = eoh + bytes_written;
00578         memcpy(new_eoh, sto->body.s + eoh_offset, sto->body.len - eoh_offset);
00579 
00580         // Change sto to point to the new buffer.
00581         sto->body.s = buf;
00582         sto->body.len += bytes_written;
00583         return 0;
00584 error:
00585         if(buf != NULL)
00586                 pkg_free(buf);
00587         return -1;
00588 }
00589 
00590 // Parses x-headers, saves the data back to sto, and removes the x-headers
00591 // from the message in sto->buf
00592 static int sip_trace_xheaders_read(struct _siptrace_data *sto)
00593 {
00594         char* searchend = NULL;
00595         char* eoh = NULL;
00596         char* xheaders = NULL;
00597         long long unsigned int tv_sec, tv_usec;
00598 
00599         if(xheaders_read_flag==NULL || *xheaders_read_flag==0)
00600                 return 0;
00601 
00602         // Find the end-of-header marker \r\n\r\n
00603         searchend = sto->body.s + sto->body.len - 3;
00604         eoh = memchr(sto->body.s, '\r', searchend - eoh);
00605         while (eoh != NULL && eoh < searchend) {
00606                 if (memcmp(eoh, "\r\n\r\n", 4) == 0)
00607                         break;
00608                 eoh = memchr(eoh + 1, '\r', searchend - eoh);
00609         }
00610         if (eoh == NULL) {
00611                 LM_ERR("sip_trace_xheaders_read: malformed message\n");
00612                 return -1;
00613         }
00614 
00615         // Find x-headers: eoh will be overwritten by \0 to allow the use of
00616         // strstr(). The byte at eoh will later be recovered, when the
00617         // message body is shifted towards the beginning of the message
00618         // to remove the x-headers.
00619         *eoh = '\0';
00620         xheaders = strstr(sto->body.s, "\r\nX-Siptrace-Fromip: ");
00621         if (xheaders == NULL) {
00622                 LM_ERR("sip_trace_xheaders_read: message without x-headers "
00623                                 "from %.*s, callid %.*s\n",
00624                                 sto->fromip.len, sto->fromip.s, sto->callid.len, sto->callid.s);
00625                 return -1;
00626         }
00627 
00628         // Allocate memory for new strings in sto
00629         // (gets free()ed in sip_trace_xheaders_free() )
00630         sto->fromip.s = pkg_malloc(51);
00631         sto->toip.s = pkg_malloc(51);
00632         sto->method.s = pkg_malloc(51);
00633         sto->dir = pkg_malloc(4);
00634         if (!(sto->fromip.s && sto->toip.s && sto->method.s && sto->dir)) {
00635                 LM_ERR("sip_trace_xheaders_read: out of memory\n");
00636                 goto erroraftermalloc;
00637         }
00638 
00639         // Parse the x-headers: scanf()
00640         if (sscanf(xheaders, "\r\n"
00641                                 "X-Siptrace-Fromip: %50s\r\n"
00642                                 "X-Siptrace-Toip: %50s\r\n"
00643                                 "X-Siptrace-Time: %llu %llu\r\n"
00644                                 "X-Siptrace-Method: %50s\r\n"
00645                                 "X-Siptrace-Dir: %3s",
00646                                 sto->fromip.s, sto->toip.s,
00647                                 &tv_sec, &tv_usec,
00648                                 sto->method.s,
00649                                 sto->dir) == EOF) {
00650                 LM_ERR("sip_trace_xheaders_read: malformed x-headers\n");
00651                 goto erroraftermalloc;
00652         }
00653         sto->fromip.len = strlen(sto->fromip.s);
00654         sto->toip.len = strlen(sto->toip.s);
00655         sto->tv.tv_sec = (time_t)tv_sec;
00656         sto->tv.tv_usec = (suseconds_t)tv_usec;
00657         sto->method.len = strlen(sto->method.s);
00658 
00659         // Remove the x-headers: the message body is shifted towards the beginning
00660         // of the message, overwriting the x-headers. Before that, the byte at eoh
00661         // is recovered.
00662         *eoh = '\r';
00663         memmove(xheaders, eoh, sto->body.len - (eoh - sto->body.s));
00664         sto->body.len -= eoh - xheaders;
00665 
00666         return 0;
00667 
00668 erroraftermalloc:
00669         if (sto->fromip.s)
00670                 pkg_free(sto->fromip.s);
00671         if (sto->toip.s)
00672                 pkg_free(sto->toip.s);
00673         if (sto->method.s)
00674                 pkg_free(sto->method.s);
00675         if (sto->dir)
00676                 pkg_free(sto->dir);
00677         return -1;
00678 }
00679 
00680 // Frees the memory allocated by sip_trace_xheaders_{write,read}
00681 static int sip_trace_xheaders_free(struct _siptrace_data *sto)
00682 {
00683         if (xheaders_write_flag != NULL && *xheaders_write_flag != 0) {
00684                 if(sto->body.s)
00685                         pkg_free(sto->body.s);
00686         }
00687 
00688         if (xheaders_read_flag != NULL && *xheaders_read_flag != 0) {
00689                 if(sto->fromip.s)
00690                         pkg_free(sto->fromip.s);
00691                 if(sto->toip.s)
00692                         pkg_free(sto->toip.s);
00693                 if(sto->dir)
00694                         pkg_free(sto->dir);
00695         }
00696 
00697         return 0;
00698 }
00699 
00700 static int sip_trace_store(struct _siptrace_data *sto)
00701 {
00702         if(sto==NULL)
00703         {
00704                 LM_DBG("invalid parameter\n");
00705                 return -1;
00706         }
00707 
00708         gettimeofday(&sto->tv, NULL);
00709 
00710         if (sip_trace_xheaders_read(sto) != 0)
00711                 return -1;
00712         int ret = sip_trace_store_db(sto);
00713 
00714         if (sip_trace_xheaders_write(sto) != 0)
00715                 return -1;
00716 
00717         if(hep_mode_on) trace_send_hep_duplicate(&sto->body, &sto->fromip, &sto->toip);
00718         else trace_send_duplicate(sto->body.s, sto->body.len);
00719 
00720         if (sip_trace_xheaders_free(sto) != 0)
00721                 return -1;
00722 
00723         return ret;
00724 }
00725 
00726 static int sip_trace_store_db(struct _siptrace_data *sto)
00727 {
00728         if(trace_to_database_flag==NULL || *trace_to_database_flag==0)
00729                 goto done;
00730 
00731         db_key_t db_keys[NR_KEYS];
00732         db_val_t db_vals[NR_KEYS];
00733 
00734         db_keys[0] = &msg_column;
00735         db_vals[0].type = DB1_BLOB;
00736         db_vals[0].nul = 0;
00737         db_vals[0].val.blob_val = sto->body;
00738 
00739         db_keys[1] = &callid_column;
00740         db_vals[1].type = DB1_STR;
00741         db_vals[1].nul = 0;
00742         db_vals[1].val.str_val = sto->callid;
00743 
00744         db_keys[2] = &method_column;
00745         db_vals[2].type = DB1_STR;
00746         db_vals[2].nul = 0;
00747         db_vals[2].val.str_val = sto->method;
00748 
00749         db_keys[3] = &status_column;
00750         db_vals[3].type = DB1_STR;
00751         db_vals[3].nul = 0;
00752         db_vals[3].val.str_val = sto->status;
00753 
00754         db_keys[4] = &fromip_column;
00755         db_vals[4].type = DB1_STR;
00756         db_vals[4].nul = 0;
00757         db_vals[4].val.str_val = sto->fromip;
00758 
00759         db_keys[5] = &toip_column;
00760         db_vals[5].type = DB1_STR;
00761         db_vals[5].nul = 0;
00762         db_vals[5].val.str_val = sto->toip;
00763 
00764         db_keys[6] = &date_column;
00765         db_vals[6].type = DB1_DATETIME;
00766         db_vals[6].nul = 0;
00767         db_vals[6].val.time_val = sto->tv.tv_sec;
00768 
00769         db_keys[7] = &direction_column;
00770         db_vals[7].type = DB1_STRING;
00771         db_vals[7].nul = 0;
00772         db_vals[7].val.string_val = sto->dir;
00773 
00774         db_keys[8] = &fromtag_column;
00775         db_vals[8].type = DB1_STR;
00776         db_vals[8].nul = 0;
00777         db_vals[8].val.str_val = sto->fromtag;
00778 
00779         db_keys[9] = &traced_user_column;
00780         db_vals[9].type = DB1_STR;
00781         db_vals[9].nul = 0;
00782 
00783         db_keys[10] = &time_us_column;
00784         db_vals[10].type = DB1_INT;
00785         db_vals[10].nul = 0;
00786         db_vals[10].val.int_val = sto->tv.tv_usec;
00787 
00788         db_funcs.use_table(db_con, siptrace_get_table());
00789 
00790         if(trace_on_flag!=NULL && *trace_on_flag!=0) {
00791                 db_vals[9].val.str_val.s   = "";
00792                 db_vals[9].val.str_val.len = 0;
00793 
00794                 LM_DBG("storing info...\n");
00795                 if(trace_delayed!=0 && db_funcs.insert_delayed!=NULL)
00796                 {
00797                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS)<0) {
00798                                 LM_ERR("error storing trace\n");
00799                                 goto error;
00800                         }
00801                 } else {
00802                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
00803                                 LM_ERR("error storing trace\n");
00804                                 goto error;
00805                         }
00806                 }
00807 #ifdef STATISTICS
00808                 update_stat(sto->stat, 1);
00809 #endif
00810         }
00811 
00812         if(sto->avp==NULL)
00813                 goto done;
00814 
00815         db_vals[9].val.str_val = sto->avp_value.s;
00816 
00817         LM_DBG("storing info...\n");
00818         if(trace_delayed!=0 && db_funcs.insert_delayed!=NULL)
00819         {
00820                 if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
00821                         LM_ERR("error storing trace\n");
00822                         goto error;
00823                 }
00824         } else {
00825                 if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
00826                         LM_ERR("error storing trace\n");
00827                         goto error;
00828                 }
00829         }
00830 
00831         sto->avp = search_next_avp(&sto->state, &sto->avp_value);
00832         while(sto->avp!=NULL) {
00833                 db_vals[9].val.str_val = sto->avp_value.s;
00834 
00835                 LM_DBG("storing info...\n");
00836                 if(trace_delayed!=0 && db_funcs.insert_delayed!=NULL)
00837                 {
00838                         if(db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
00839                                 LM_ERR("error storing trace\n");
00840                                 goto error;
00841                         }
00842                 } else {
00843                         if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
00844                                 LM_ERR("error storing trace\n");
00845                                 goto error;
00846                         }
00847                 }
00848                 sto->avp = search_next_avp(&sto->state, &sto->avp_value);
00849         }
00850 
00851 done:
00852         return 1;
00853 error:
00854         return -1;
00855 }
00856 
00857 static int sip_trace(struct sip_msg *msg, char *dir, char *s2)
00858 {
00859         struct _siptrace_data sto;
00860         struct onsend_info *snd_inf = NULL;
00861 
00862         if(msg==NULL) {
00863                 LM_DBG("nothing to trace\n");
00864                 return -1;
00865         }
00866         memset(&sto, 0, sizeof(struct _siptrace_data));
00867 
00868         if(traced_user_avp.n!=0)
00869                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
00870                                 &sto.avp_value, &sto.state);
00871 
00872         if((sto.avp==NULL) && (trace_on_flag==NULL || *trace_on_flag==0)) {
00873                 LM_DBG("trace off...\n");
00874                 return -1;
00875         }
00876         if(sip_trace_prepare(msg)<0)
00877                 return -1;
00878 
00879         sto.callid = msg->callid->body;
00880 
00881         if(msg->first_line.type==SIP_REQUEST) {
00882                 sto.method = msg->first_line.u.request.method;
00883         } else {
00884                 if(parse_headers(msg, HDR_CSEQ_F, 0) != 0 || msg->cseq==NULL
00885                                 || msg->cseq->parsed==NULL) {
00886                         LM_ERR("cannot parse cseq header\n");
00887                         return -1;
00888                 }
00889                 sto.method = get_cseq(msg)->method;
00890         }
00891 
00892         if(msg->first_line.type==SIP_REPLY) {
00893                 sto.status = msg->first_line.u.reply.status;
00894         } else {
00895                 sto.status.s = "";
00896                 sto.status.len = 0;
00897         }
00898 
00899         snd_inf=get_onsend_info();
00900         if(snd_inf==NULL) {
00901                 sto.body.s = msg->buf;
00902                 sto.body.len = msg->len;
00903 
00904                 siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
00905                 strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.src_ip));
00906                 strcat(sto.fromip_buff,":");
00907                 strcat(sto.fromip_buff, int2str(msg->rcv.src_port, NULL));
00908                 sto.fromip.s = sto.fromip_buff;
00909                 sto.fromip.len = strlen(sto.fromip_buff);
00910 
00911                 siptrace_copy_proto(msg->rcv.proto, sto.toip_buff);
00912                 strcat(sto.toip_buff, ip_addr2a(&msg->rcv.dst_ip));
00913                 strcat(sto.toip_buff,":");
00914                 strcat(sto.toip_buff, int2str(msg->rcv.dst_port, NULL));
00915                 sto.toip.s = sto.toip_buff;
00916                 sto.toip.len = strlen(sto.toip_buff);
00917 
00918                 sto.dir = (dir)?dir:"in";
00919         } else {
00920                 sto.body.s   = snd_inf->buf;
00921                 sto.body.len = snd_inf->len;
00922 
00923                 strncpy(sto.fromip_buff, snd_inf->send_sock->sock_str.s,
00924                                 snd_inf->send_sock->sock_str.len);
00925                 sto.fromip.s = sto.fromip_buff;
00926                 sto.fromip.len = strlen(sto.fromip_buff);
00927 
00928                 siptrace_copy_proto(snd_inf->send_sock->proto, sto.toip_buff);
00929                 strcat(sto.toip_buff, suip2a(snd_inf->to, sizeof(*snd_inf->to)));
00930                 strcat(sto.toip_buff,":");
00931                 strcat(sto.toip_buff, int2str((int)su_getport(snd_inf->to), NULL));
00932                 sto.toip.s = sto.toip_buff;
00933                 sto.toip.len = strlen(sto.toip_buff);
00934 
00935                 sto.dir = "out";
00936         }
00937 
00938         sto.fromtag = get_from(msg)->tag_value;
00939 
00940 #ifdef STATISTICS
00941         if(msg->first_line.type==SIP_REPLY) {
00942                 sto.stat = siptrace_rpl;
00943         } else {
00944                 sto.stat = siptrace_req;
00945         }
00946 #endif
00947         return sip_trace_store(&sto);
00948 }
00949 
00950 #define trace_is_off(_msg) \
00951         (trace_on_flag==NULL || *trace_on_flag==0 || \
00952          ((_msg)->flags&trace_flag)==0)
00953 
00954 static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps)
00955 {
00956         struct sip_msg* msg;
00957         int_str         avp_value;
00958         struct usr_avp* avp;
00959 
00960         if(t==NULL || ps==NULL)
00961         {
00962                 LM_DBG("no uas request, local transaction\n");
00963                 return;
00964         }
00965 
00966         msg = ps->req;
00967         if(msg==NULL)
00968         {
00969                 LM_DBG("no uas request, local transaction\n");
00970                 return;
00971         }
00972 
00973         avp = NULL;
00974         if(traced_user_avp.n!=0)
00975                 avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value,
00976                                 0);
00977 
00978         if((avp==NULL) && trace_is_off(msg))
00979         {
00980                 LM_DBG("trace off...\n");
00981                 return;
00982         }
00983 
00984         if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL)
00985         {
00986                 LM_ERR("cannot parse FROM header\n");
00987                 return;
00988         }
00989 
00990         if(parse_headers(msg, HDR_CALLID_F, 0)!=0)
00991         {
00992                 LM_ERR("cannot parse call-id\n");
00993                 return;
00994         }
00995 
00996         if(tmb.register_tmcb(0, t, TMCB_REQUEST_SENT, trace_onreq_out, 0, 0) <=0)
00997         {
00998                 LM_ERR("can't register trace_onreq_out\n");
00999                 return;
01000         }
01001         if(tmb.register_tmcb(0, t, TMCB_RESPONSE_IN, trace_onreply_in, 0, 0) <=0)
01002         {
01003                 LM_ERR("can't register trace_onreply_in\n");
01004                 return;
01005         }
01006 
01007         if(tmb.register_tmcb(0, t, TMCB_RESPONSE_SENT, trace_onreply_out, 0, 0)<=0)
01008         {
01009                 LM_ERR("can't register trace_onreply_out\n");
01010                 return;
01011         }
01012 }
01013 
01014 static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps)
01015 {
01016         struct _siptrace_data sto;
01017         sip_msg_t *msg;
01018         struct ip_addr to_ip;
01019         int len;
01020         struct dest_info *dst;
01021 
01022         if(t==NULL || ps==NULL) {
01023                 LM_DBG("very weird\n");
01024                 return;
01025         }
01026 
01027         if(ps->flags&TMCB_RETR_F) {
01028                 LM_DBG("retransmission\n");
01029                 return;
01030         }
01031         msg=ps->req;
01032         if(msg==NULL) {
01033                 /* check if it is outgoing cancel, t is INVITE
01034                  * and send_buf starts with CANCEL */
01035                 if(is_invite(t) && ps->send_buf.len>7
01036                                 && strncmp(ps->send_buf.s, "CANCEL ", 7)==0) {
01037                         msg = t->uas.request;
01038                         if(msg==NULL) {
01039                                 LM_DBG("no uas msg for INVITE transaction\n");
01040                                 return;
01041                         } else {
01042                                 LM_DBG("recording CANCEL based on INVITE transaction\n");
01043                         }
01044                 } else {
01045                         LM_DBG("no uas msg, local transaction\n");
01046                         return;
01047                 }
01048         }
01049         memset(&sto, 0, sizeof(struct _siptrace_data));
01050 
01051         if(traced_user_avp.n!=0)
01052                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
01053                                 &sto.avp_value, &sto.state);
01054 
01055         if((sto.avp==NULL) && trace_is_off(msg) ) {
01056                 LM_DBG("trace off...\n");
01057                 return;
01058         }
01059 
01060         if(sip_trace_prepare(msg)<0)
01061                 return;
01062 
01063         if(ps->send_buf.len>0) {
01064                 sto.body = ps->send_buf;
01065         } else {
01066                 sto.body.s   = "No request buffer";
01067                 sto.body.len = sizeof("No request buffer")-1;
01068         }
01069 
01070         sto.callid = msg->callid->body;
01071 
01072         if(ps->send_buf.len>10) {
01073                 sto.method.s = ps->send_buf.s;
01074                 sto.method.len = 0;
01075                 while(sto.method.len<ps->send_buf.len) {
01076                         if(ps->send_buf.s[sto.method.len]==' ')
01077                                 break;
01078                         sto.method.len++;
01079                 }
01080                 if(sto.method.len==ps->send_buf.len)
01081                         sto.method.len = 10;
01082         } else {
01083                 sto.method = t->method;
01084         }
01085 
01086         sto.status.s = "";
01087         sto.status.len = 0;
01088 
01089         memset(&to_ip, 0, sizeof(struct ip_addr));
01090         dst = ps->dst;
01091 
01092         if (trace_local_ip.s && trace_local_ip.len > 0) {
01093                 sto.fromip = trace_local_ip;
01094         } else {
01095                 if(dst==0 || dst->send_sock==0 || dst->send_sock->sock_str.s==0) {
01096                         siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
01097                         strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.dst_ip));
01098                         strcat(sto.fromip_buff,":");
01099                         strcat(sto.fromip_buff, int2str(msg->rcv.dst_port, NULL));
01100                         sto.fromip.s = sto.fromip_buff;
01101                         sto.fromip.len = strlen(sto.fromip_buff);
01102                 } else {
01103                         sto.fromip = dst->send_sock->sock_str;
01104                 }
01105         }
01106 
01107         if(dst==0) {
01108                 sto.toip.s = "any:255.255.255.255";
01109                 sto.toip.len = 19;
01110         } else {
01111                 su2ip_addr(&to_ip, &dst->to);
01112                 siptrace_copy_proto(dst->proto, sto.toip_buff);
01113                 strcat(sto.toip_buff, ip_addr2a(&to_ip));
01114                 strcat(sto.toip_buff, ":");
01115                 strcat(sto.toip_buff,
01116                                 int2str((unsigned long)su_getport(&dst->to), &len));
01117                 sto.toip.s = sto.toip_buff;
01118                 sto.toip.len = strlen(sto.toip_buff);
01119         }
01120 
01121         sto.dir = "out";
01122 
01123         sto.fromtag = get_from(msg)->tag_value;
01124 
01125 #ifdef STATISTICS
01126         sto.stat = siptrace_req;
01127 #endif
01128 
01129         sip_trace_store(&sto);
01130         return;
01131 }
01132 
01133 static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps)
01134 {
01135         struct _siptrace_data sto;
01136         sip_msg_t *msg;
01137         sip_msg_t *req;
01138         char statusbuf[8];
01139 
01140         if(t==NULL || t->uas.request==0 || ps==NULL) {
01141                 LM_DBG("no uas request, local transaction\n");
01142                 return;
01143         }
01144 
01145         req = ps->req;
01146         msg = ps->rpl;
01147         if(msg==NULL || req==NULL) {
01148                 LM_DBG("no reply\n");
01149                 return;
01150         }
01151         memset(&sto, 0, sizeof(struct _siptrace_data));
01152 
01153         if(traced_user_avp.n!=0)
01154                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
01155                                 &sto.avp_value, &sto.state);
01156 
01157         if((sto.avp==NULL) &&  trace_is_off(req)) {
01158                 LM_DBG("trace off...\n");
01159                 return;
01160         }
01161 
01162         if(sip_trace_prepare(msg)<0)
01163                 return;
01164 
01165         sto.body.s = msg->buf;
01166         sto.body.len = msg->len;
01167 
01168         sto.callid = msg->callid->body;
01169 
01170         sto.method = t->method;
01171 
01172         strcpy(statusbuf, int2str(ps->code, &sto.status.len));
01173         sto.status.s = statusbuf;
01174 
01175         siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
01176         strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.src_ip));
01177         strcat(sto.fromip_buff,":");
01178         strcat(sto.fromip_buff, int2str(msg->rcv.src_port, NULL));
01179         sto.fromip.s = sto.fromip_buff;
01180         sto.fromip.len = strlen(sto.fromip_buff);
01181 
01182         if(trace_local_ip.s && trace_local_ip.len > 0) {
01183                 sto.toip = trace_local_ip;
01184         } else {
01185                 siptrace_copy_proto(msg->rcv.proto, sto.toip_buff);
01186                 strcat(sto.toip_buff, ip_addr2a(&msg->rcv.dst_ip));
01187                 strcat(sto.toip_buff,":");
01188                 strcat(sto.toip_buff, int2str(msg->rcv.dst_port, NULL));
01189                 sto.toip.s = sto.toip_buff;
01190                 sto.toip.len = strlen(sto.toip_buff);
01191         }
01192 
01193         sto.dir = "in";
01194 
01195         sto.fromtag = get_from(msg)->tag_value;
01196 #ifdef STATISTICS
01197         sto.stat = siptrace_rpl;
01198 #endif
01199 
01200         sip_trace_store(&sto);
01201         return;
01202 }
01203 
01204 static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps)
01205 {
01206         struct _siptrace_data sto;
01207         int faked = 0;
01208         struct sip_msg* msg;
01209         struct sip_msg* req;
01210         struct ip_addr to_ip;
01211         int len;
01212         char statusbuf[8];
01213         struct dest_info *dst;
01214 
01215         if (t==NULL || t->uas.request==0 || ps==NULL) {
01216                 LM_DBG("no uas request, local transaction\n");
01217                 return;
01218         }
01219 
01220         if(ps->flags&TMCB_RETR_F) {
01221                 LM_DBG("retransmission\n");
01222                 return;
01223         }
01224         memset(&sto, 0, sizeof(struct _siptrace_data));
01225         if(traced_user_avp.n!=0)
01226                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
01227                                 &sto.avp_value, &sto.state);
01228 
01229         if((sto.avp==NULL) &&  trace_is_off(t->uas.request)) {
01230                 LM_DBG("trace off...\n");
01231                 return;
01232         }
01233 
01234         req = ps->req;
01235         msg = ps->rpl;
01236         if(msg==NULL || msg==FAKED_REPLY) {
01237                 msg = t->uas.request;
01238                 faked = 1;
01239         }
01240 
01241         if(sip_trace_prepare(msg)<0)
01242                 return;
01243 
01244         if(faked==0) {
01245                 if(ps->send_buf.len>0) {
01246                         sto.body = ps->send_buf;
01247                 } else if(t->uas.response.buffer!=NULL) {
01248                         sto.body.s = t->uas.response.buffer;
01249                         sto.body.len = t->uas.response.buffer_len;
01250                 } else if(msg->len>0) {
01251                         sto.body.s = msg->buf;
01252                         sto.body.len = msg->len;
01253                 } else {
01254                         sto.body.s = "No reply buffer";
01255                         sto.body.len = sizeof("No reply buffer")-1;
01256                 }
01257         } else {
01258                 if(ps->send_buf.len>0) {
01259                         sto.body = ps->send_buf;
01260                 } else if(t->uas.response.buffer!=NULL) {
01261                         sto.body.s = t->uas.response.buffer;
01262                         sto.body.len = t->uas.response.buffer_len;
01263                 } else {
01264                         sto.body.s = "No reply buffer";
01265                         sto.body.len = sizeof("No reply buffer")-1;
01266                 }
01267         }
01268 
01269         sto.callid = msg->callid->body;
01270         sto.method = t->method;
01271 
01272         if(trace_local_ip.s && trace_local_ip.len > 0) {
01273                 sto.fromip = trace_local_ip;
01274         } else {
01275                 siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
01276                 strcat(sto.fromip_buff, ip_addr2a(&req->rcv.dst_ip));
01277                 strcat(sto.fromip_buff,":");
01278                 strcat(sto.fromip_buff, int2str(req->rcv.dst_port, NULL));
01279                 sto.fromip.s = sto.fromip_buff;
01280                 sto.fromip.len = strlen(sto.fromip_buff);
01281         }
01282 
01283         strcpy(statusbuf, int2str(ps->code, &sto.status.len));
01284         sto.status.s = statusbuf;
01285 
01286         memset(&to_ip, 0, sizeof(struct ip_addr));
01287         dst = ps->dst;
01288         if(dst==0) {
01289                 sto.toip.s = "any:255.255.255.255";
01290                 sto.toip.len = 19;
01291         } else {
01292                 su2ip_addr(&to_ip, &dst->to);
01293                 siptrace_copy_proto(dst->proto, sto.toip_buff);
01294                 strcat(sto.toip_buff, ip_addr2a(&to_ip));
01295                 strcat(sto.toip_buff, ":");
01296                 strcat(sto.toip_buff,
01297                                 int2str((unsigned long)su_getport(&dst->to), &len));
01298                 sto.toip.s = sto.toip_buff;
01299                 sto.toip.len = strlen(sto.toip_buff);
01300         }
01301 
01302         sto.dir = "out";
01303         sto.fromtag = get_from(msg)->tag_value;
01304 
01305 #ifdef STATISTICS
01306         sto.stat = siptrace_rpl;
01307 #endif
01308 
01309         sip_trace_store(&sto);
01310         return;
01311 }
01312 
01313 static void trace_sl_ack_in(sl_cbp_t *slcbp)
01314 {
01315         sip_msg_t *req;
01316         LM_DBG("storing ack...\n");
01317         req = slcbp->req;
01318         sip_trace(req, 0, 0);
01319 }
01320 
01321 static void trace_sl_onreply_out(sl_cbp_t *slcbp)
01322 {
01323         sip_msg_t *req;
01324         struct _siptrace_data sto;
01325         struct sip_msg* msg;
01326         struct ip_addr to_ip;
01327         int len;
01328         char statusbuf[5];
01329 
01330         if(slcbp==NULL || slcbp->req==NULL)
01331         {
01332                 LM_ERR("bad parameters\n");
01333                 return;
01334         }
01335         req = slcbp->req;
01336 
01337         memset(&sto, 0, sizeof(struct _siptrace_data));
01338         if(traced_user_avp.n!=0)
01339                 sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp,
01340                                 &sto.avp_value, &sto.state);
01341 
01342         if((sto.avp==NULL) && trace_is_off(req)) {
01343                 LM_DBG("trace off...\n");
01344                 return;
01345         }
01346 
01347         msg = req;
01348 
01349         if(sip_trace_prepare(msg)<0)
01350                 return;
01351 
01352         sto.body.s = (slcbp->reply)?slcbp->reply->s:"";
01353         sto.body.len = (slcbp->reply)?slcbp->reply->len:0;
01354 
01355         sto.callid = msg->callid->body;
01356         sto.method = msg->first_line.u.request.method;
01357 
01358         if(trace_local_ip.len > 0) {
01359                 sto.fromip = trace_local_ip;
01360         } else {
01361                 siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff);
01362                 strcat(sto.fromip_buff, ip_addr2a(&req->rcv.dst_ip));
01363                 strcat(sto.fromip_buff,":");
01364                 strcat(sto.fromip_buff, int2str(req->rcv.dst_port, NULL));
01365                 sto.fromip.s = sto.fromip_buff;
01366                 sto.fromip.len = strlen(sto.fromip_buff);
01367         }
01368 
01369         strcpy(statusbuf, int2str(slcbp->code, &sto.status.len));
01370         sto.status.s = statusbuf;
01371 
01372         memset(&to_ip, 0, sizeof(struct ip_addr));
01373         if(slcbp->dst==0)
01374         {
01375                 sto.toip.s = "any:255.255.255.255";
01376                 sto.toip.len = 19;
01377         } else {
01378                 su2ip_addr(&to_ip, &slcbp->dst->to);
01379                 siptrace_copy_proto(req->rcv.proto, sto.toip_buff);
01380                 strcat(sto.toip_buff, ip_addr2a(&to_ip));
01381                 strcat(sto.toip_buff, ":");
01382                 strcat(sto.toip_buff,
01383                                 int2str((unsigned long)su_getport(&slcbp->dst->to), &len));
01384                 sto.toip.s = sto.toip_buff;
01385                 sto.toip.len = strlen(sto.toip_buff);
01386         }
01387 
01388         sto.dir = "out";
01389         sto.fromtag = get_from(msg)->tag_value;
01390 
01391 #ifdef STATISTICS
01392         sto.stat = siptrace_rpl;
01393 #endif
01394 
01395         sip_trace_store(&sto);
01396         return;
01397 }
01398 
01399 
01407 static struct mi_root* sip_trace_mi(struct mi_root* cmd_tree, void* param )
01408 {
01409         struct mi_node* node;
01410 
01411         struct mi_node *rpl; 
01412         struct mi_root *rpl_tree ; 
01413 
01414         node = cmd_tree->node.kids;
01415         if(node == NULL) {
01416                 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
01417                 if (rpl_tree == 0)
01418                         return 0;
01419                 rpl = &rpl_tree->node;
01420 
01421                 if (*trace_on_flag == 0 ) {
01422                         node = add_mi_node_child(rpl,0,0,0,MI_SSTR("off"));
01423                 } else if (*trace_on_flag == 1) {
01424                         node = add_mi_node_child(rpl,0,0,0,MI_SSTR("on"));
01425                 }
01426                 return rpl_tree ;
01427         }
01428         if(trace_on_flag==NULL)
01429                 return init_mi_tree( 500, MI_SSTR(MI_INTERNAL_ERR));
01430 
01431         if ( node->value.len==2 && (node->value.s[0]=='o'
01432                                 || node->value.s[0]=='O') &&
01433                         (node->value.s[1]=='n'|| node->value.s[1]=='N')) {
01434                 *trace_on_flag = 1;
01435                 return init_mi_tree( 200, MI_SSTR(MI_OK));
01436         } else if ( node->value.len==3 && (node->value.s[0]=='o'
01437                                 || node->value.s[0]=='O')
01438                         && (node->value.s[1]=='f'|| node->value.s[1]=='F')
01439                         && (node->value.s[2]=='f'|| node->value.s[2]=='F')) {
01440                 *trace_on_flag = 0;
01441                 return init_mi_tree( 200, MI_SSTR(MI_OK));
01442         } else {
01443                 return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
01444         }
01445 }
01446 
01447 static int trace_send_duplicate(char *buf, int len)
01448 {
01449         struct dest_info dst;
01450         struct proxy_l * p;
01451 
01452         if(buf==NULL || len <= 0)
01453                 return -1;
01454 
01455         if(dup_uri_str.s==0 || dup_uri==NULL)
01456                 return 0;
01457 
01458         init_dest_info(&dst);
01459         /* create a temporary proxy*/
01460         dst.proto = PROTO_UDP;
01461         p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,
01462                         dst.proto);
01463         if (p==0)
01464         {
01465                 LM_ERR("bad host name in uri\n");
01466                 return -1;
01467         }
01468 
01469         hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
01470 
01471         dst.send_sock=get_send_socket(0, &dst.to, dst.proto);
01472         if (dst.send_sock==0)
01473         {
01474                 LM_ERR("can't forward to af %d, proto %d no corresponding"
01475                                 " listening socket\n", dst.to.s.sa_family, dst.proto);
01476                 goto error;
01477         }
01478 
01479         if (msg_send(&dst, buf, len)<0)
01480         {
01481                 LM_ERR("cannot send duplicate message\n");
01482                 goto error;
01483         }
01484 
01485         free_proxy(p); /* frees only p content, not p itself */
01486         pkg_free(p);
01487         return 0;
01488 error:
01489         free_proxy(p); /* frees only p content, not p itself */
01490         pkg_free(p);
01491         return -1;
01492 }
01493 
01494 static int trace_send_hep_duplicate(str *body, str *from, str *to)
01495 {
01496         struct dest_info dst;
01497         struct proxy_l * p=NULL /* make gcc happy */;
01498         void* buffer = NULL;
01499         union sockaddr_union from_su;
01500         union sockaddr_union to_su;
01501         unsigned int len, buflen, proto;
01502         struct hep_hdr hdr;
01503         struct hep_iphdr hep_ipheader;
01504         struct hep_timehdr hep_time;
01505         struct timeval tvb;
01506         struct timezone tz;
01507                          
01508 #if USE_IPV6
01509         struct hep_ip6hdr hep_ip6header;
01510 #endif
01511 
01512         if(body->s==NULL || body->len <= 0)
01513                 return -1;
01514 
01515         if(dup_uri_str.s==0 || dup_uri==NULL)
01516                 return 0;
01517 
01518 
01519         gettimeofday( &tvb, &tz );
01520         
01521 
01522         /* message length */
01523         len = body->len 
01524 #if USE_IPV6
01525                 + sizeof(struct hep_ip6hdr)
01526 #else
01527                 + sizeof(struct hep_iphdr)          
01528 #endif
01529                 + sizeof(struct hep_hdr) + sizeof(struct hep_timehdr);;
01530 
01531 
01532         /* The packet is too big for us */
01533         if (unlikely(len>BUF_SIZE)){
01534                 goto error;
01535         }
01536 
01537         /* Convert proto:ip:port to sockaddress union SRC IP */
01538         if (pipport2su(from->s, &from_su, &proto)==-1 || (pipport2su(to->s, &to_su, &proto)==-1))
01539                 goto error;
01540 
01541         /* check if from and to are in the same family*/
01542         if(from_su.s.sa_family != to_su.s.sa_family) {
01543                 LOG(L_ERR, "ERROR: trace_send_hep_duplicate: interworking detected ?\n");
01544                 goto error;
01545         }
01546 
01547         init_dest_info(&dst);
01548         /* create a temporary proxy*/
01549         dst.proto = PROTO_UDP;
01550         p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,
01551                         dst.proto);
01552         if (p==0)
01553         {
01554                 LM_ERR("bad host name in uri\n");
01555                 goto error;
01556         }
01557 
01558         hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
01559 
01560         dst.send_sock=get_send_socket(0, &dst.to, dst.proto);
01561         if (dst.send_sock==0)
01562         {
01563                 LM_ERR("can't forward to af %d, proto %d no corresponding"
01564                                 " listening socket\n", dst.to.s.sa_family, dst.proto);
01565                 goto error;
01566         }
01567 
01568         /* Version && proto && length */
01569         hdr.hp_l = sizeof(struct hep_hdr);
01570         hdr.hp_v = hep_version;
01571         hdr.hp_p = proto;
01572 
01573         /* AND the last */
01574         if (from_su.s.sa_family==AF_INET){
01575                 /* prepare the hep headers */
01576 
01577                 hdr.hp_f = AF_INET;
01578                 hdr.hp_sport = htons(from_su.sin.sin_port);
01579                 hdr.hp_dport = htons(to_su.sin.sin_port);
01580 
01581                 hep_ipheader.hp_src = from_su.sin.sin_addr;
01582                 hep_ipheader.hp_dst = to_su.sin.sin_addr;
01583 
01584                 len = sizeof(struct hep_iphdr);
01585         }
01586 #ifdef USE_IPV6
01587         else if (from_su.s.sa_family==AF_INET6){
01588                 /* prepare the hep6 headers */
01589 
01590                 hdr.hp_f = AF_INET6;
01591 
01592                 hdr.hp_sport = htons(from_su.sin6.sin6_port);
01593                 hdr.hp_dport = htons(to_su.sin6.sin6_port);
01594 
01595                 hep_ip6header.hp6_src = from_su.sin6.sin6_addr;
01596                 hep_ip6header.hp6_dst = to_su.sin6.sin6_addr;
01597 
01598                 len = sizeof(struct hep_ip6hdr);
01599         }
01600 #endif /* USE_IPV6 */
01601         else {
01602                 LOG(L_ERR, "ERROR: trace_send_hep_duplicate: Unsupported protocol family\n");
01603                 goto error;;
01604         }
01605 
01606         hdr.hp_l +=len;
01607         len += sizeof(struct hep_hdr) + body->len;
01608         buffer = (void *)pkg_malloc(len+1);
01609         if (buffer==0){
01610                 LOG(L_ERR, "ERROR: trace_send_hep_duplicate: out of memory\n");
01611                 goto error;
01612         }
01613 
01614         /* Copy job */
01615         memset(buffer, '\0', len+1);
01616 
01617         /* copy hep_hdr */
01618         memcpy((void*)buffer, &hdr, sizeof(struct hep_hdr));
01619         buflen = sizeof(struct hep_hdr);
01620 
01621         /* hep_ip_hdr */
01622         if(from_su.s.sa_family==AF_INET) {
01623                 memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
01624                 buflen += sizeof(struct hep_iphdr);
01625         }
01626 #if USE_IPV6
01627         else {
01628                 memcpy((void*)buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
01629                 buflen += sizeof(struct hep_ip6hdr);
01630         }
01631 #endif /* USE_IPV6 */
01632 
01633         if(hep_version == 2) {
01634 
01635                 hep_time.tv_sec = tvb.tv_sec;
01636                 hep_time.tv_usec = tvb.tv_usec;
01637                 hep_time.captid = hep_capture_id;
01638 
01639                 memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr));
01640                 buflen += sizeof(struct hep_timehdr);
01641         }
01642 
01643         /* PAYLOAD */
01644         memcpy((void*)(buffer + buflen) , (void*)body->s, body->len);
01645         buflen +=body->len;
01646 
01647         if (msg_send(&dst, buffer, buflen)<0)
01648         {
01649                 LM_ERR("cannot send hep duplicate message\n");
01650                 goto error;
01651         }
01652 
01653         free_proxy(p); /* frees only p content, not p itself */
01654         pkg_free(p);
01655         pkg_free(buffer);
01656         return 0;
01657 error:
01658         if(p)
01659         {
01660                 free_proxy(p); /* frees only p content, not p itself */
01661                 pkg_free(p);
01662         }
01663         if(buffer) pkg_free(buffer);
01664         return -1;
01665 }
01666 
01675 static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto)
01676 {
01677         unsigned int port_no, cutlen = 4;
01678         struct ip_addr *ip;
01679         char *p, *host_s;
01680         str port_str, host_uri;
01681         unsigned len = 0;
01682         char tmp_piport[256];
01683 
01684         /*parse protocol */
01685         if(strncmp(pipport, "udp:",4) == 0) *proto = IPPROTO_UDP;
01686         else if(strncmp(pipport, "tcp:",4) == 0) *proto = IPPROTO_TCP;
01687         else if(strncmp(pipport, "tls:",4) == 0) *proto = IPPROTO_IDP; /* fake proto type */
01688 #ifdef USE_SCTP
01689         else if(strncmp(pipport, "sctp:",5) == 0) cutlen = 5, *proto = IPPROTO_SCTP;
01690 #endif
01691         else if(strncmp(pipport, "any:",4) == 0) *proto = IPPROTO_UDP;
01692         else {
01693                 LM_ERR("bad protocol %s\n", pipport);
01694                 return -1;
01695         }
01696         
01697         if((len = strlen(pipport)) >= 256) {
01698                 LM_ERR("too big pipport\n");
01699                 goto error;
01700         }
01701 
01702         /* our tmp string */
01703         strncpy(tmp_piport, pipport, len+1);
01704 
01705         len = 0;
01706 
01707         /*separate proto and host */
01708         p = tmp_piport+cutlen;
01709         if( (*(p)) == '\0') {
01710                 LM_ERR("malformed ip address\n");
01711                 goto error;
01712         }
01713         host_s=p;
01714 
01715         if( (p = strrchr(p+1, ':')) == 0 ) {
01716                 LM_DBG("no port specified\n");
01717                 port_no = 0;
01718         }
01719         else {
01720                 /*the address contains a port number*/
01721                 *p = '\0';
01722                 p++;
01723                 port_str.s = p;
01724                 port_str.len = strlen(p);
01725                 LM_DBG("the port string is %s\n", p);
01726                 if(str2int(&port_str, &port_no) != 0 ) {
01727                         LM_ERR("there is not a valid number port\n");
01728                         goto error;
01729                 }
01730                 *p = '\0';
01731         }
01732         
01733         /* now IPv6 address has no brakets. It should be fixed! */
01734         if (host_s[0] == '[') {
01735                 len = strlen(host_s + 1) - 1;
01736                 if(host_s[len+1] != ']') {
01737                         LM_ERR("bracket not closed\n");
01738                         goto error;
01739                 }
01740                 memmove(host_s, host_s + 1, len);
01741                 host_s[len] = '\0';
01742         }
01743 
01744         host_uri.s = host_s;
01745         host_uri.len = strlen(host_s);
01746 
01747         /* check if it's an ip address */
01748         if (((ip=str2ip(&host_uri))!=0)
01749 #ifdef  USE_IPV6
01750                         || ((ip=str2ip6(&host_uri))!=0)
01751 #endif
01752            ) {
01753                 ip_addr2su(tmp_su, ip, ntohs(port_no));
01754                 return 0;       
01755 
01756         }
01757 
01758 error:
01759         return -1;
01760 }