Przeglądaj źródła

sipdump: refactored to enable more storage engines

- pass data via structure instead of data printed in text format
Daniel-Constantin Mierla 5 lat temu
rodzic
commit
b7ddcfb191

+ 125 - 172
src/modules/sipdump/sipdump_mod.c

@@ -47,7 +47,7 @@ int sipdump_rotate = 7200;
 static int sipdump_wait = 100;
 static str sipdump_folder = str_init("/tmp");
 static str sipdump_fprefix = str_init("kamailio-sipdump-");
-static int sipdump_mode = SIPDUMP_MODE_WFILE;
+int sipdump_mode = SIPDUMP_MODE_WTEXT;
 static str sipdump_event_callback = STR_NULL;
 
 static int sipdump_event_route_idx = -1;
@@ -112,7 +112,8 @@ struct module_exports exports = {
  */
 static int mod_init(void)
 {
-	if(!(sipdump_mode & (SIPDUMP_MODE_WFILE | SIPDUMP_MODE_EVROUTE))) {
+	if(!(sipdump_mode & (SIPDUMP_MODE_WTEXT |SIPDUMP_MODE_WPCAP
+							| SIPDUMP_MODE_EVROUTE))) {
 		LM_ERR("invalid mode parameter\n");
 		return -1;
 	}
@@ -143,7 +144,7 @@ static int mod_init(void)
 		}
 	}
 
-	if(sipdump_mode & SIPDUMP_MODE_WFILE) {
+	if(sipdump_mode & (SIPDUMP_MODE_WTEXT|SIPDUMP_MODE_WPCAP)) {
 		register_basic_timers(1);
 	}
 
@@ -162,7 +163,7 @@ static int child_init(int rank)
 	if(rank != PROC_MAIN)
 		return 0;
 
-	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+	if(!(sipdump_mode & (SIPDUMP_MODE_WTEXT|SIPDUMP_MODE_WPCAP))) {
 		return 0;
 	}
 
@@ -184,115 +185,59 @@ static void mod_destroy(void)
 	sipdump_list_destroy();
 }
 
-#define SIPDUMP_WBUF_SIZE 65536
-static char _sipdump_wbuf[SIPDUMP_WBUF_SIZE];
-
-typedef struct sipdump_info {
-	str tag;
-	str buf;
-	str af;
-	str proto;
-	str src_ip;
-	int src_port;
-	str dst_ip;
-	int dst_port;
-} sipdump_info_t;
-
-/**
- *
- */
-int sipdump_buffer_write(sipdump_info_t *sdi, str *obuf)
-{
-	struct timeval tv;
-	struct tm ti;
-	char t_buf[26] = {0};
-
-	gettimeofday(&tv, NULL);
-	localtime_r(&tv.tv_sec, &ti);
-	obuf->len = snprintf(_sipdump_wbuf, SIPDUMP_WBUF_SIZE,
-		"====================\n"
-		"tag: %.*s\n"
-		"pid: %d\n"
-		"process: %d\n"
-		"time: %lu.%06lu\n"
-		"date: %s"
-		"proto: %.*s %.*s\n"
-		"srcip: %.*s\n"
-		"srcport: %d\n"
-		"dstip: %.*s\n"
-		"dstport: %d\n"
-		"~~~~~~~~~~~~~~~~~~~~\n"
-		"%.*s"
-		"||||||||||||||||||||\n",
-		sdi->tag.len, sdi->tag.s,
-		my_pid(),
-		process_no,
-		(unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec,
-		asctime_r(&ti, t_buf),
-		sdi->proto.len, sdi->proto.s, sdi->af.len, sdi->af.s,
-		sdi->src_ip.len, sdi->src_ip.s, sdi->src_port,
-		sdi->dst_ip.len, sdi->dst_ip.s, sdi->dst_port,
-		sdi->buf.len, sdi->buf.s
-	);
-	obuf->s = _sipdump_wbuf;
-
-	return 0;
-}
-
 /**
  *
  */
 int ki_sipdump_send(sip_msg_t *msg, str *stag)
 {
-	str wdata;
-	sipdump_info_t sdi;
+	sipdump_data_t isd;
+	sipdump_data_t *osd = NULL;
 	char srcip_buf[IP_ADDR_MAX_STRZ_SIZE];
 
 	if(!sipdump_enabled())
 		return 1;
 
-	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+	if(!(sipdump_mode & (SIPDUMP_MODE_WTEXT|SIPDUMP_MODE_WPCAP))) {
 		LM_WARN("writing to file is disabled - ignoring\n");
 		return 1;
 	}
 
-	memset(&sdi, 0, sizeof(sipdump_info_t));
+	memset(&isd, 0, sizeof(sipdump_data_t));
 
-	sdi.buf.s = msg->buf;
-	sdi.buf.len = msg->len;
-	sdi.tag = *stag;
-	sdi.src_ip.len = ip_addr2sbufz(&msg->rcv.src_ip, srcip_buf,
+	gettimeofday(&isd.tv, NULL);
+	isd.data.s = msg->buf;
+	isd.data.len = msg->len;
+	isd.pid = my_pid();
+	isd.procno = process_no;
+	isd.tag = *stag;
+	isd.protoid = msg->rcv.proto;
+	isd.afid = msg->rcv.src_ip.af;
+	isd.src_ip.len = ip_addr2sbufz(&msg->rcv.src_ip, srcip_buf,
 			IP_ADDR_MAX_STRZ_SIZE);
-	sdi.src_ip.s = srcip_buf;
-	sdi.src_port = msg->rcv.src_port;
+	isd.src_ip.s = srcip_buf;
+	isd.src_port = msg->rcv.src_port;
 	if(msg->rcv.bind_address==NULL
 			|| msg->rcv.bind_address->address_str.s==NULL) {
-		sdi.dst_ip.len = 7;
-		sdi.dst_ip.s = "0.0.0.0";
-		sdi.dst_port = 0;
-	} else {
-		sdi.dst_ip = msg->rcv.bind_address->address_str;
-		sdi.dst_port = (int)msg->rcv.bind_address->port_no;
-	}
-
-	sdi.af.len = 4;
-	if(msg->rcv.bind_address!=NULL
-			&& msg->rcv.bind_address->address.af==AF_INET6) {
-		sdi.af.s = "ipv6";
+		if(msg->rcv.src_ip.af == AF_INET6) {
+			isd.dst_ip.len = 3;
+			isd.dst_ip.s = "::2";
+		} else {
+			isd.dst_ip.len = 7;
+			isd.dst_ip.s = "0.0.0.0";
+		}
+		isd.dst_port = 0;
 	} else {
-		sdi.af.s = "ipv4";
+		isd.dst_ip = msg->rcv.bind_address->address_str;
+		isd.dst_port = (int)msg->rcv.bind_address->port_no;
 	}
-	sdi.proto.s = "none";
-	sdi.proto.len = 4;
-	get_valid_proto_string(msg->rcv.proto, 0, 0, &sdi.proto);
 
-	if(sipdump_buffer_write(&sdi, &wdata)<0) {
-		LM_ERR("failed to write to buffer\n");
+	if(sipdump_data_clone(&isd, &osd)<0) {
+		LM_ERR("failed to clone sipdump data\n");
 		return -1;
 	}
 
-	if(sipdump_list_add(&wdata)<0) {
-		LM_ERR("failed to add data to write list\n");
+	if(sipdump_list_add(osd)<0) {
+		LM_ERR("failed to add data to dump queue\n");
 		return -1;
 	}
 	return 1;
@@ -318,12 +263,12 @@ static int w_sipdump_send(sip_msg_t *msg, char *ptag, char *str2)
 /**
  *
  */
-static sipdump_info_t* sipdump_event_info = NULL;
+static sipdump_data_t* sipdump_event_data = NULL;
 
 /**
  *
  */
-int sipdump_event_route(sipdump_info_t* sdi)
+int sipdump_event_route(sipdump_data_t* sdi)
 {
 	int backup_rt;
 	run_act_ctx_t ctx;
@@ -336,7 +281,7 @@ int sipdump_event_route(sipdump_info_t* sdi)
 	set_route_type(EVENT_ROUTE);
 	init_run_actions_ctx(&ctx);
 	fmsg = faked_msg_next();
-	sipdump_event_info = sdi;
+	sipdump_event_data = sdi;
 
 	if(sipdump_event_route_idx>=0) {
 		run_top_route(event_rt.rlist[sipdump_event_route_idx], fmsg, 0);
@@ -350,7 +295,7 @@ int sipdump_event_route(sipdump_info_t* sdi)
 			sr_kemi_act_ctx_set(bctx);
 		}
 	}
-	sipdump_event_info = NULL;
+	sipdump_event_data = NULL;
 	set_route_type(backup_rt);
 	if(ctx.run_flags & DROP_R_F) {
 		return DROP_R_F;
@@ -363,60 +308,61 @@ int sipdump_event_route(sipdump_info_t* sdi)
  */
 int sipdump_msg_received(sr_event_param_t *evp)
 {
-	str wdata;
-	sipdump_info_t sdi;
+	sipdump_data_t isd;
+	sipdump_data_t *osd = NULL;
 	char srcip_buf[IP_ADDR_MAX_STRZ_SIZE];
 
 	if(!sipdump_enabled())
 		return 0;
 
-	memset(&sdi, 0, sizeof(sipdump_info_t));
-
-	sdi.buf = *((str*)evp->data);
-	sdi.tag.s = "rcv";
-	sdi.tag.len = 3;
-	sdi.src_ip.len = ip_addr2sbufz(&evp->rcv->src_ip, srcip_buf,
+	memset(&isd, 0, sizeof(sipdump_data_t));
+
+	gettimeofday(&isd.tv, NULL);
+	isd.data = *((str*)evp->data);
+	isd.tag.s = "rcv";
+	isd.tag.len = 3;
+	isd.pid = my_pid();
+	isd.procno = process_no;
+	isd.protoid = evp->rcv->proto;
+	isd.afid = (evp->rcv->bind_address!=NULL
+				&& evp->rcv->bind_address->address.af==AF_INET6)?AF_INET6:AF_INET;
+	isd.src_ip.len = ip_addr2sbufz(&evp->rcv->src_ip, srcip_buf,
 					IP_ADDR_MAX_STRZ_SIZE);
-	sdi.src_ip.s = srcip_buf;
-	sdi.src_port = evp->rcv->src_port;
+	isd.src_ip.s = srcip_buf;
+	isd.src_port = evp->rcv->src_port;
 	if(evp->rcv->bind_address==NULL
 			|| evp->rcv->bind_address->address_str.s==NULL) {
-		sdi.dst_ip.len = 7;
-		sdi.dst_ip.s = "0.0.0.0";
-		sdi.dst_port = 0;
-	} else {
-		sdi.dst_ip = evp->rcv->bind_address->address_str;
-		sdi.dst_port = (int)evp->rcv->bind_address->port_no;
-	}
-	sdi.af.len = 4;
-	if(evp->rcv->bind_address!=NULL
-			&& evp->rcv->bind_address->address.af==AF_INET6) {
-		sdi.af.s = "ipv6";
+		if(isd.afid == AF_INET6) {
+			isd.dst_ip.len = 3;
+			isd.dst_ip.s = "::2";
+		} else {
+			isd.dst_ip.len = 7;
+			isd.dst_ip.s = "0.0.0.0";
+		}
+		isd.dst_port = 0;
 	} else {
-		sdi.af.s = "ipv4";
+		isd.dst_ip = evp->rcv->bind_address->address_str;
+		isd.dst_port = (int)evp->rcv->bind_address->port_no;
 	}
-	sdi.proto.s = "none";
-	sdi.proto.len = 4;
-	get_valid_proto_string(evp->rcv->proto, 0, 0, &sdi.proto);
 
 	if(sipdump_mode & SIPDUMP_MODE_EVROUTE) {
-		if(sipdump_event_route(&sdi) == DROP_R_F) {
+		if(sipdump_event_route(&isd) == DROP_R_F) {
 			/* drop() used in event_route - all done */
 			return 0;
 		}
 	}
 
-	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+	if(!(sipdump_mode & (SIPDUMP_MODE_WTEXT|SIPDUMP_MODE_WPCAP))) {
 		return 0;
 	}
 
-	if(sipdump_buffer_write(&sdi, &wdata)<0) {
-		LM_ERR("failed to write to buffer\n");
+	if(sipdump_data_clone(&isd, &osd)<0) {
+		LM_ERR("failed to close sipdump data\n");
 		return -1;
 	}
 
-	if(sipdump_list_add(&wdata)<0) {
-		LM_ERR("failed to add data to write list\n");
+	if(sipdump_list_add(osd)<0) {
+		LM_ERR("failed to add data to dump queue\n");
 		return -1;
 	}
 	return 0;
@@ -427,58 +373,58 @@ int sipdump_msg_received(sr_event_param_t *evp)
  */
 int sipdump_msg_sent(sr_event_param_t *evp)
 {
-	str wdata;
-	sipdump_info_t sdi;
+	sipdump_data_t isd;
+	sipdump_data_t *osd = NULL;
 	ip_addr_t ip;
 	char dstip_buf[IP_ADDR_MAX_STRZ_SIZE];
 
 	if(!sipdump_enabled())
 		return 0;
 
-	memset(&sdi, 0, sizeof(sipdump_info_t));
+	memset(&isd, 0, sizeof(sipdump_data_t));
 
-	sdi.buf = *((str*)evp->data);
-	sdi.tag.s = "snd";
-	sdi.tag.len = 3;
+	gettimeofday(&isd.tv, NULL);
+	isd.data = *((str*)evp->data);
+	isd.tag.s = "snd";
+	isd.tag.len = 3;
+	isd.pid = my_pid();
+	isd.procno = process_no;
+	isd.protoid = evp->dst->proto;
+	isd.afid = evp->dst->send_sock->address.af;
 
 	if(evp->dst->send_sock==NULL || evp->dst->send_sock->address_str.s==NULL) {
-		sdi.src_ip.len = 7;
-		sdi.src_ip.s = "0.0.0.0";
-		sdi.src_port = 0;
+		if(evp->dst->send_sock->address.af == AF_INET6) {
+			isd.src_ip.len = 3;
+			isd.src_ip.s = "::2";
+		} else {
+			isd.src_ip.len = 7;
+			isd.src_ip.s = "0.0.0.0";
+		}
+		isd.src_port = 0;
 	} else {
-		sdi.src_ip = evp->dst->send_sock->address_str;
-		sdi.src_port = (int)evp->dst->send_sock->port_no;
+		isd.src_ip = evp->dst->send_sock->address_str;
+		isd.src_port = (int)evp->dst->send_sock->port_no;
 	}
 	su2ip_addr(&ip, &evp->dst->to);
-	sdi.dst_ip.len = ip_addr2sbufz(&ip, dstip_buf, IP_ADDR_MAX_STRZ_SIZE);
-	sdi.dst_ip.s = dstip_buf;
-	sdi.dst_port = (int)su_getport(&evp->dst->to);
-
-	sdi.af.len = 4;
-	if(evp->dst->send_sock->address.af==AF_INET6) {
-		sdi.af.s = "ipv6";
-	} else {
-		sdi.af.s = "ipv4";
-	}
-	sdi.proto.s = "none";
-	sdi.proto.len = 4;
-	get_valid_proto_string(evp->dst->proto, 0, 0, &sdi.proto);
+	isd.dst_ip.len = ip_addr2sbufz(&ip, dstip_buf, IP_ADDR_MAX_STRZ_SIZE);
+	isd.dst_ip.s = dstip_buf;
+	isd.dst_port = (int)su_getport(&evp->dst->to);
 
 	if(sipdump_mode & SIPDUMP_MODE_EVROUTE) {
-		sipdump_event_route(&sdi);
+		sipdump_event_route(&isd);
 	}
 
-	if(!(sipdump_mode & SIPDUMP_MODE_WFILE)) {
+	if(!(sipdump_mode & (SIPDUMP_MODE_WTEXT|SIPDUMP_MODE_WPCAP))) {
 		return 0;
 	}
 
-	if(sipdump_buffer_write(&sdi, &wdata)<0) {
-		LM_ERR("failed to write to buffer\n");
+	if(sipdump_data_clone(&isd, &osd)<0) {
+		LM_ERR("failed to clone sipdump data\n");
 		return -1;
 	}
 
-	if(sipdump_list_add(&wdata)<0) {
-		LM_ERR("failed to add data to write list\n");
+	if(sipdump_list_add(osd)<0) {
+		LM_ERR("failed to add data to dump queue\n");
 		return -1;
 	}
 	return 0;
@@ -496,12 +442,12 @@ static sr_kemi_xval_t* ki_sipdump_get_buf(sip_msg_t *msg)
 {
 	memset(&_ksr_kemi_sipdump_xval, 0, sizeof(sr_kemi_xval_t));
 
-	if (sipdump_event_info==NULL) {
+	if (sipdump_event_data==NULL) {
 		sr_kemi_xval_null(&_ksr_kemi_sipdump_xval, SR_KEMI_XVAL_NULL_EMPTY);
 		return &_ksr_kemi_sipdump_xval;
 	}
 	_ksr_kemi_sipdump_xval.vtype = SR_KEMIP_STR;
-	_ksr_kemi_sipdump_xval.v.s = sipdump_event_info->buf;
+	_ksr_kemi_sipdump_xval.v.s = sipdump_event_data->data;
 	return &_ksr_kemi_sipdump_xval;
 }
 
@@ -512,12 +458,12 @@ static sr_kemi_xval_t* ki_sipdump_get_tag(sip_msg_t *msg)
 {
 	memset(&_ksr_kemi_sipdump_xval, 0, sizeof(sr_kemi_xval_t));
 
-	if (sipdump_event_info==NULL) {
+	if (sipdump_event_data==NULL) {
 		sr_kemi_xval_null(&_ksr_kemi_sipdump_xval, SR_KEMI_XVAL_NULL_EMPTY);
 		return &_ksr_kemi_sipdump_xval;
 	}
 	_ksr_kemi_sipdump_xval.vtype = SR_KEMIP_STR;
-	_ksr_kemi_sipdump_xval.v.s = sipdump_event_info->tag;
+	_ksr_kemi_sipdump_xval.v.s = sipdump_event_data->tag;
 	return &_ksr_kemi_sipdump_xval;
 }
 
@@ -528,12 +474,12 @@ static sr_kemi_xval_t* ki_sipdump_get_src_ip(sip_msg_t *msg)
 {
 	memset(&_ksr_kemi_sipdump_xval, 0, sizeof(sr_kemi_xval_t));
 
-	if (sipdump_event_info==NULL) {
+	if (sipdump_event_data==NULL) {
 		sr_kemi_xval_null(&_ksr_kemi_sipdump_xval, SR_KEMI_XVAL_NULL_EMPTY);
 		return &_ksr_kemi_sipdump_xval;
 	}
 	_ksr_kemi_sipdump_xval.vtype = SR_KEMIP_STR;
-	_ksr_kemi_sipdump_xval.v.s = sipdump_event_info->src_ip;
+	_ksr_kemi_sipdump_xval.v.s = sipdump_event_data->src_ip;
 	return &_ksr_kemi_sipdump_xval;
 }
 
@@ -544,12 +490,12 @@ static sr_kemi_xval_t* ki_sipdump_get_dst_ip(sip_msg_t *msg)
 {
 	memset(&_ksr_kemi_sipdump_xval, 0, sizeof(sr_kemi_xval_t));
 
-	if (sipdump_event_info==NULL) {
+	if (sipdump_event_data==NULL) {
 		sr_kemi_xval_null(&_ksr_kemi_sipdump_xval, SR_KEMI_XVAL_NULL_EMPTY);
 		return &_ksr_kemi_sipdump_xval;
 	}
 	_ksr_kemi_sipdump_xval.vtype = SR_KEMIP_STR;
-	_ksr_kemi_sipdump_xval.v.s = sipdump_event_info->dst_ip;
+	_ksr_kemi_sipdump_xval.v.s = sipdump_event_data->dst_ip;
 	return &_ksr_kemi_sipdump_xval;
 }
 
@@ -652,30 +598,37 @@ error:
 int pv_get_sipdump(sip_msg_t *msg, pv_param_t *param,
 		pv_value_t *res)
 {
-	if (sipdump_event_info==NULL) {
+	str saf = str_init("ipv4");
+	str sproto = str_init("none");
+
+	if (sipdump_event_data==NULL) {
 		return pv_get_null(msg, param, res);
 	}
 
 	switch(param->pvn.u.isname.name.n) {
 		case 1: /* buf */
-			return pv_get_strval(msg, param, res, &sipdump_event_info->buf);
+			return pv_get_strval(msg, param, res, &sipdump_event_data->data);
 		case 2: /* len */
-			return pv_get_uintval(msg, param, res, sipdump_event_info->buf.len);
+			return pv_get_uintval(msg, param, res, sipdump_event_data->data.len);
 		case 3: /* af */
-			return pv_get_strval(msg, param, res, &sipdump_event_info->af);
+			if(sipdump_event_data->afid==AF_INET6) {
+				saf.s = "ipv6";
+			}
+			return pv_get_strval(msg, param, res, &saf);
 		case 4: /* proto */
-			return pv_get_strval(msg, param, res, &sipdump_event_info->proto);
+			get_valid_proto_string(sipdump_event_data->protoid, 0, 0, &sproto);
+			return pv_get_strval(msg, param, res, &sproto);
 		case 6: /* src_ip*/
-			return pv_get_strval(msg, param, res, &sipdump_event_info->src_ip);
+			return pv_get_strval(msg, param, res, &sipdump_event_data->src_ip);
 		case 7: /* dst_ip*/
-			return pv_get_strval(msg, param, res, &sipdump_event_info->dst_ip);
+			return pv_get_strval(msg, param, res, &sipdump_event_data->dst_ip);
 		case 8: /* src_port */
-			return pv_get_uintval(msg, param, res, sipdump_event_info->src_port);
+			return pv_get_uintval(msg, param, res, sipdump_event_data->src_port);
 		case 9: /* dst_port */
-			return pv_get_uintval(msg, param, res, sipdump_event_info->dst_port);
+			return pv_get_uintval(msg, param, res, sipdump_event_data->dst_port);
 		default:
 			/* 0 - tag */
-			return pv_get_strval(msg, param, res, &sipdump_event_info->tag);
+			return pv_get_strval(msg, param, res, &sipdump_event_data->tag);
 	}
 }
 

+ 158 - 35
src/modules/sipdump/sipdump_write.c

@@ -36,6 +36,7 @@
 #include "sipdump_write.h"
 
 extern int sipdump_rotate;
+extern int sipdump_mode;
 
 static time_t sipdump_last_rotate = 0;
 
@@ -45,7 +46,8 @@ static sipdump_list_t *_sipdump_list = NULL;
 static char _sipdump_fpath[SIPDUMP_FPATH_SIZE];
 static str _sipdump_fpath_prefix = {0, 0};
 
-static FILE *_sipdump_file = NULL;
+static FILE *_sipdump_text_file = NULL;
+static FILE *_sipdump_pcap_file = NULL;
 
 /**
  *
@@ -102,21 +104,8 @@ int sipdump_list_destroy(void)
 /**
  *
  */
-int sipdump_list_add(str *data)
+int sipdump_list_add(sipdump_data_t *sdd)
 {
-	sipdump_data_t *sdd = NULL;
-
-	sdd = (sipdump_data_t*)shm_malloc(sizeof(sipdump_data_t)
-				+ (data->len+1)*sizeof(char));
-	if(sdd==NULL) {
-		LM_ERR("no more shared memory\n");
-		return -1;
-	}
-	memset(sdd, 0, sizeof(sipdump_data_t));
-	sdd->data.s = (char*)sdd + sizeof(sipdump_data_t);
-	sdd->data.len = data->len;
-	memcpy(sdd->data.s, data->s, data->len);
-	sdd->data.s[data->len] = '\0';
 	lock_get(&_sipdump_list->lock);
 	if(_sipdump_list->last) {
 		_sipdump_list->last->next = sdd;
@@ -128,6 +117,53 @@ int sipdump_list_add(str *data)
 	return 0;
 }
 
+/**
+ *
+ */
+int sipdump_data_clone(sipdump_data_t *isd, sipdump_data_t **osd)
+{
+	int dsize = 0;
+	sipdump_data_t *sdd = NULL;
+
+	*osd = NULL;
+
+	dsize = sizeof(sipdump_data_t) + (isd->data.len + 1 + isd->tag.len + 1
+				+ isd->src_ip.len + 1 + isd->dst_ip.len + 1)*sizeof(char);
+	sdd = (sipdump_data_t*)shm_malloc(dsize);
+	if(sdd==NULL) {
+		LM_ERR("no more shared memory\n");
+		return -1;
+	}
+	memset(sdd, 0, dsize);
+
+	memcpy(sdd, isd, sizeof(sipdump_data_t));
+	sdd->next = NULL;
+
+	sdd->data.s = (char*)sdd + sizeof(sipdump_data_t);
+	sdd->data.len = isd->data.len;
+	memcpy(sdd->data.s, isd->data.s, isd->data.len);
+	sdd->data.s[sdd->data.len] = '\0';
+
+	sdd->tag.s = sdd->data.s + sdd->data.len + 1;
+	sdd->tag.len = isd->tag.len;
+	memcpy(sdd->tag.s, isd->tag.s, isd->tag.len);
+	sdd->tag.s[sdd->tag.len] = '\0';
+
+	sdd->src_ip.s = sdd->tag.s + sdd->tag.len + 1;
+	sdd->src_ip.len = isd->src_ip.len;
+	memcpy(sdd->src_ip.s, isd->src_ip.s, isd->src_ip.len);
+	sdd->src_ip.s[sdd->src_ip.len] = '\0';
+
+	sdd->dst_ip.s = sdd->src_ip.s + sdd->src_ip.len + 1;
+	sdd->dst_ip.len = isd->dst_ip.len;
+	memcpy(sdd->dst_ip.s, isd->dst_ip.s, isd->dst_ip.len);
+	sdd->dst_ip.s[sdd->dst_ip.len] = '\0';
+
+	*osd = sdd;
+
+	return 0;
+}
+
 /**
  *
  */
@@ -188,28 +224,54 @@ static int sipdump_rotate_file(void)
 
 	tv = time(NULL);
 
-	if(_sipdump_file!=NULL
+	if(_sipdump_text_file!=NULL
+			&& sipdump_last_rotate>0
+			&& sipdump_last_rotate+sipdump_rotate>tv) {
+		/* not yet the time for rotation */
+		return 0;
+	}
+	if(_sipdump_pcap_file!=NULL
 			&& sipdump_last_rotate>0
 			&& sipdump_last_rotate+sipdump_rotate>tv) {
 		/* not yet the time for rotation */
 		return 0;
 	}
 
-	if(_sipdump_file != NULL) {
-		fclose(_sipdump_file);
+	if(_sipdump_text_file != NULL) {
+		fclose(_sipdump_text_file);
+	}
+	if(_sipdump_pcap_file != NULL) {
+		fclose(_sipdump_pcap_file);
 	}
+
 	localtime_r(&tv, &ti);
-	n = snprintf(_sipdump_fpath+_sipdump_fpath_prefix.len,
-			SIPDUMP_FPATH_SIZE-_sipdump_fpath_prefix.len,
-			"%d-%02d-%02d--%02d-%02d-%02d.data",
-			1900+ti.tm_year, ti.tm_mon+1, ti.tm_mday,
-			ti.tm_hour, ti.tm_min, ti.tm_sec);
-	LM_DBG("writing to file: %s (%d)\n", _sipdump_fpath, n);
-	_sipdump_file = fopen( _sipdump_fpath, "w" );
-	if(_sipdump_file==NULL) {
-		LM_ERR("failed to open file %s\n", _sipdump_fpath);
-		return -1;
+	if(sipdump_mode & SIPDUMP_MODE_WTEXT) {
+		n = snprintf(_sipdump_fpath+_sipdump_fpath_prefix.len,
+				SIPDUMP_FPATH_SIZE-_sipdump_fpath_prefix.len,
+				"%d-%02d-%02d--%02d-%02d-%02d.data",
+				1900+ti.tm_year, ti.tm_mon+1, ti.tm_mday,
+				ti.tm_hour, ti.tm_min, ti.tm_sec);
+		LM_DBG("writing to text file: %s (%d)\n", _sipdump_fpath, n);
+		_sipdump_text_file = fopen( _sipdump_fpath, "w" );
+		if(_sipdump_text_file==NULL) {
+			LM_ERR("failed to open file %s\n", _sipdump_fpath);
+			return -1;
+		}
 	}
+	if(sipdump_mode & SIPDUMP_MODE_WPCAP) {
+		n = snprintf(_sipdump_fpath+_sipdump_fpath_prefix.len,
+				SIPDUMP_FPATH_SIZE-_sipdump_fpath_prefix.len,
+				"%d-%02d-%02d--%02d-%02d-%02d.pcap",
+				1900+ti.tm_year, ti.tm_mon+1, ti.tm_mday,
+				ti.tm_hour, ti.tm_min, ti.tm_sec);
+		LM_DBG("writing to pcap file: %s (%d)\n", _sipdump_fpath, n);
+		_sipdump_pcap_file = fopen( _sipdump_fpath, "w" );
+		if(_sipdump_pcap_file==NULL) {
+			LM_ERR("failed to open file %s\n", _sipdump_fpath);
+			return -1;
+		}
+	}
+
 	sipdump_write_meta(_sipdump_fpath);
 	sipdump_last_rotate = tv;
 
@@ -234,12 +296,63 @@ int sipdump_file_init(str *folder, str *fprefix)
 	return 0;
 }
 
+#define SIPDUMP_WBUF_SIZE 65536
+static char _sipdump_wbuf[SIPDUMP_WBUF_SIZE];
+
+/**
+ *
+ */
+int sipdump_data_print(sipdump_data_t *sd, str *obuf)
+{
+	struct tm ti;
+	char t_buf[26] = {0};
+	str sproto = str_init("none");
+	str saf = str_init("ipv4");
+
+	if(sd->afid==AF_INET6) {
+		saf.s = "ipv6";
+	}
+
+	get_valid_proto_string(sd->protoid, 0, 0, &sproto);
+
+	localtime_r(&sd->tv.tv_sec, &ti);
+	obuf->len = snprintf(_sipdump_wbuf, SIPDUMP_WBUF_SIZE,
+		"====================\n"
+		"tag: %.*s\n"
+		"pid: %d\n"
+		"process: %d\n"
+		"time: %lu.%06lu\n"
+		"date: %s"
+		"proto: %.*s %.*s\n"
+		"srcip: %.*s\n"
+		"srcport: %d\n"
+		"dstip: %.*s\n"
+		"dstport: %d\n"
+		"~~~~~~~~~~~~~~~~~~~~\n"
+		"%.*s"
+		"||||||||||||||||||||\n",
+		sd->tag.len, sd->tag.s,
+		sd->pid,
+		sd->procno,
+		(unsigned long)sd->tv.tv_sec, (unsigned long)sd->tv.tv_usec,
+		asctime_r(&ti, t_buf),
+		sproto.len, sproto.s, saf.len, saf.s,
+		sd->src_ip.len, sd->src_ip.s, sd->src_port,
+		sd->dst_ip.len, sd->dst_ip.s, sd->dst_port,
+		sd->data.len, sd->data.s
+	);
+	obuf->s = _sipdump_wbuf;
+
+	return 0;
+}
+
 /**
  *
  */
 void sipdump_timer_exec(unsigned int ticks, void *param)
 {
 	sipdump_data_t *sdd = NULL;
+	str odata = str_init("");
 	int cnt = 0;
 
 	if(_sipdump_list==NULL || _sipdump_list->first==NULL)
@@ -254,7 +367,7 @@ void sipdump_timer_exec(unsigned int ticks, void *param)
 		lock_get(&_sipdump_list->lock);
 		if(_sipdump_list->first==NULL) {
 			lock_release(&_sipdump_list->lock);
-			if(_sipdump_file) fflush(_sipdump_file);
+			if(_sipdump_text_file) fflush(_sipdump_text_file);
 			return;
 		}
 		sdd = _sipdump_list->first;
@@ -272,13 +385,23 @@ void sipdump_timer_exec(unsigned int ticks, void *param)
 			}
 			cnt=0;
 		}
-		if(_sipdump_file==NULL) {
-			LM_ERR("sipdump file is not open\n");
-			return;
+		if(sipdump_mode & SIPDUMP_MODE_WTEXT) {
+			if(_sipdump_text_file==NULL) {
+				LM_ERR("sipdump text file is not open\n");
+				return;
+			}
+			sipdump_data_print(sdd, &odata);
+			/* LM_NOTICE("writing: [[%.*s]] (%d)\n", odata.len,
+					odata.s, odata.len); */
+			fwrite(odata.s, 1, odata.len, _sipdump_text_file);
+		}
+		if(sipdump_mode & SIPDUMP_MODE_WPCAP) {
+			if(_sipdump_pcap_file==NULL) {
+				LM_ERR("sipdump pcap file is not open\n");
+				return;
+			}
+			sipdump_write_pcap(_sipdump_pcap_file, sdd);
 		}
-		/* LM_NOTICE("writing: [[%.*s]] (%d)\n",
-			sdd->data.len, sdd->data.s, sdd->data.len); */
-		fwrite(sdd->data.s, 1, sdd->data.len, _sipdump_file);
 		shm_free(sdd);
 	}
 }

+ 24 - 2
src/modules/sipdump/sipdump_write.h

@@ -23,14 +23,28 @@
 #ifndef _SIPDUMP_WRITE_H_
 #define _SIPDUMP_WRITE_H_
 
+#include <sys/time.h>
+
 #include "../../core/str.h"
 #include "../../core/locking.h"
 
-#define SIPDUMP_MODE_WFILE (1<<0)
+#define SIPDUMP_MODE_WTEXT (1<<0)
 #define SIPDUMP_MODE_EVROUTE (1<<1)
+#define SIPDUMP_MODE_WPCAP (1<<2)
+#define SIPDUMP_MODE_WPCAPEX (1<<3)
 
 typedef struct sipdump_data {
+	int pid;
+	int procno;
+	struct timeval tv;
 	str data;
+	str tag;
+	int afid;
+	int protoid;
+	str src_ip;
+	int src_port;
+	str dst_ip;
+	int dst_port;
 	struct sipdump_data *next;
 } sipdump_data_t;
 
@@ -46,12 +60,20 @@ int sipdump_list_init(int en);
 
 int sipdump_list_destroy(void);
 
-int sipdump_list_add(str *data);
+int sipdump_list_add(sipdump_data_t *sdd);
 
 void sipdump_timer_exec(unsigned int ticks, void *param);
 
 int sipdump_file_init(str *folder, str *fprefix);
 
+void sipdump_init_pcap(FILE *fs);
+
+void sipdump_write_pcap(FILE *fs, sipdump_data_t *sd);
+
+int sipdump_data_print(sipdump_data_t *sd, str *obuf);
+
+int sipdump_data_clone(sipdump_data_t *isd, sipdump_data_t **osd);
+
 int sipdump_enabled(void);
 
 int sipdump_rpc_init(void);