Browse code

modules/sipcapture: Added support for multiple capture modes. (c) Dragos Dinu (1and1)

Alexandr Dubovikov authored on 23/07/2013 08:37:03
Showing 2 changed files
... ...
@@ -196,6 +196,26 @@ modparam("sipcapture", "capture_on", 1)
196 196
 </programlisting>
197 197
 		</example>
198 198
 	</section>
199
+
200
+	<section id="sipcapture.p.capture_mode">
201
+                <title><varname>capture_mode</varname> (integer)</title>
202
+                <para>
203
+				This parameter can be used for defining a capture mode which can be used in
204
+				the sip_capture calls as a parameter. A capture mode has a name and some parameters.
205
+				It must be defined in the format: name=>param1=val1;param2=val2;...
206
+				The parameters are db_url, table_name, mt_mode and hash_source (optional).
207
+				Multiple capture modes can be defined by using this parameter multiple times.
208
+				After this, the capture modes can be used like:
209
+				sip_capture ("", "CAPTURE_MODE");
210
+				</para>
211
+                <example>
212
+                <title>capture_mode example</title>
213
+                <programlisting format="linespecific">
214
+modparam("sipcapture", "capture_mode", "mode1=>db_url=mysql://user:passwd@host/dbname1;table_name=homer_capture1|homer_capture2;mt_mode=hash;hash_source=call_id;")
215
+modparam("sipcapture", "capture_mode", "mode2=>db_url=mysql://user:passwd@host/dbname2;table_name=homer_capture3|homer_capture4;mt_mode=rand;")
216
+</programlisting>
217
+                </example>
218
+        </section>
199 219
 	<section id="sipcapture.p.hep_capture_on">
200 220
                 <title><varname>hep_capture_on</varname> (integer)</title>
201 221
                 <para>
... ...
@@ -95,14 +95,43 @@ MODULE_VERSION
95 95
 
96 96
 #define NR_KEYS 36
97 97
 
98
+/*multiple table mode*/
99
+enum e_mt_mode{
100
+	mode_random = 1,
101
+	mode_hash,
102
+	mode_round_robin,
103
+	mode_error
104
+};
105
+
106
+
107
+typedef struct _capture_mode_data {
108
+	unsigned int id;
109
+	str name;
110
+	str db_url;
111
+	db1_con_t *db_con;
112
+	db_func_t db_funcs;
113
+	str * table_names;
114
+	unsigned int no_tables;
115
+	enum e_mt_mode mtmode;
116
+	enum hash_source hash_source;
117
+	unsigned int rr_idx;
118
+	stat_var* sipcapture_req;
119
+	stat_var* sipcapture_rpl;
120
+	struct _capture_mode_data * next;
121
+}_capture_mode_data_t;
122
+
123
+_capture_mode_data_t * capture_modes_root = NULL;
124
+_capture_mode_data_t * capture_def = NULL;
125
+
98 126
 /* module function prototypes */
99 127
 static int mod_init(void);
100 128
 static int sipcapture_init_rpc(void);
101 129
 static int child_init(int rank);
102 130
 static void destroy(void);
103 131
 static int sipcapture_fixup(void** param, int param_no);
104
-static int sip_capture(struct sip_msg *msg, str *dtable);
105
-static int w_sip_capture(struct sip_msg* _m, char* _table, char* s2);
132
+static int sip_capture(struct sip_msg *msg, str *dtable,  _capture_mode_data_t *cm_data);
133
+
134
+static int w_sip_capture(struct sip_msg* _m, char* _table, _capture_mode_data_t * _cm_data, char* s2);
106 135
 int init_rawsock_children(void);
107 136
 int extract_host_port(void);
108 137
 int raw_capture_socket(struct ip_addr* ip, str* iface, int port_start, int port_end, int proto);
... ...
@@ -189,25 +218,19 @@ static struct sock_filter BPF_code[] = { { 0x28, 0, 0, 0x0000000c }, { 0x15, 0,
189 218
 };
190 219
 #endif
191 220
 
192
-db1_con_t *db_con = NULL; 		/*!< database connection */
193
-db_func_t db_funcs;      		/*!< Database functions */
221
+//db1_con_t *db_con = NULL; 		/*!< database connection */
222
+//db_func_t db_funcs;      		/*!< Database functions */
223
+
224
+//str* table_names = NULL;
194 225
 
195
-str* table_names = NULL;
196
-char* table_name_cpy = NULL;
197 226
 unsigned int no_tables = 0;
198 227
 
199
-/*multiple table mode*/
200
-enum e_mt_mode{
201
-	mode_random = 1,
202
-	mode_hash,
203
-	mode_round_robin,
204
-	mode_error
205
-};
228
+
206 229
 
207 230
 enum e_mt_mode mtmode = mode_random ;
208 231
 enum hash_source source = hs_error;
209 232
 
210
-unsigned int rr_idx = 0;
233
+//unsigned int rr_idx = 0;
211 234
 
212 235
 struct hep_timehdr* heptime;
213 236
 
... ...
@@ -218,10 +241,13 @@ struct hep_timehdr* heptime;
218 241
 static cmd_export_t cmds[] = {
219 242
 	{"sip_capture", (cmd_function)w_sip_capture, 0, 0, 0, ANY_ROUTE},
220 243
 	{"sip_capture", (cmd_function)w_sip_capture, 1, sipcapture_fixup, 0, ANY_ROUTE },	                         
244
+	{"sip_capture", (cmd_function)w_sip_capture, 2, sipcapture_fixup, 0, ANY_ROUTE },
221 245
 	{0, 0, 0, 0, 0, 0}
222 246
 };
223 247
 
224 248
 
249
+int capture_mode_param(modparam_t type, void *val);
250
+
225 251
 /*! \brief
226 252
  * Exported parameters
227 253
  */
... ...
@@ -279,9 +305,12 @@ static param_export_t params[] = {
279 305
         {"promiscious_on",  		INT_PARAM, &promisc_on   },		
280 306
         {"raw_moni_bpf_on",  		INT_PARAM, &bpf_on   },		
281 307
         {"callid_aleg_header",          STR_PARAM, &callid_aleg_header.s},
282
-	{0, 0, 0}
308
+        {"capture_mode",		STR_PARAM|USE_FUNC_PARAM, (void *)capture_mode_param},
309
+		{0, 0, 0}
283 310
 };
284 311
 
312
+
313
+
285 314
 /*! \brief
286 315
  * MI commands
287 316
  */
... ...
@@ -292,7 +321,7 @@ static mi_export_t mi_cmds[] = {
292 321
 
293 322
 
294 323
 #ifdef STATISTICS
295
-stat_var* sipcapture_req;
324
+/*stat_var* sipcapture_req;
296 325
 stat_var* sipcapture_rpl;
297 326
 
298 327
 stat_export_t sipcapture_stats[] = {
... ...
@@ -300,6 +329,8 @@ stat_export_t sipcapture_stats[] = {
300 329
 	{"captured_replies"  ,  0,  &sipcapture_rpl  },
301 330
 	{0,0,0}
302 331
 };
332
+*/
333
+stat_export_t *sipcapture_stats = NULL;
303 334
 #endif
304 335
 
305 336
 /*! \brief module exports */
... ...
@@ -309,7 +340,8 @@ struct module_exports exports = {
309 340
 	cmds,       /*!< Exported functions */
310 341
 	params,     /*!< Exported parameters */
311 342
 #ifdef STATISTICS
312
-	sipcapture_stats,  /*!< exported statistics */
343
+//	sipcapture_stats,  /*!< exported statistics */
344
+	0,
313 345
 #else
314 346
 	0,          /*!< exported statistics */
315 347
 #endif
... ...
@@ -323,13 +355,22 @@ struct module_exports exports = {
323 355
 };
324 356
 
325 357
 
326
-static int mt_init(void) {
358
+
359
+/* returns number of tables if successful
360
+ * <0 if failed
361
+ */
362
+int parse_table_names (str table_name, str ** table_names){
327 363
 
328 364
 	char *p = NULL;
329
-	int i = 0;
365
+	unsigned int no_tables;
366
+	char * table_name_cpy;
367
+	unsigned int i;
330 368
 
331 369
 	/*parse and save table names*/
332 370
 	no_tables = 1;
371
+	i = 0;
372
+
373
+	str * names;
333 374
 
334 375
 	table_name_cpy = (char *) pkg_malloc(sizeof(char) * table_name.len + 1 );
335 376
 	if (table_name_cpy == NULL){
... ...
@@ -350,8 +391,8 @@ static int mt_init(void) {
350 391
 		p++;
351 392
 	}
352 393
 
353
-	table_names = (str*)pkg_malloc(sizeof(str) * no_tables);
354
-	if(table_names == NULL) {
394
+	names = (str*)pkg_malloc(sizeof(str) * no_tables);
395
+	if(names == NULL) {
355 396
 		LM_ERR("no more pkg memory left\n");
356 397
 		return -1;
357 398
 	}
... ...
@@ -359,55 +400,292 @@ static int mt_init(void) {
359 400
 	while (p != NULL)
360 401
 	{
361 402
 		LM_INFO ("INFO: table name:%s\n",p);
362
-		table_names[i].s =  p;
363
-		table_names[i].len = strlen (p);
403
+		names[i].len = strlen (p);
404
+		names[i].s =  (char *)pkg_malloc(sizeof(char) *names[i].len);
405
+		memcpy(names[i].s, p, names[i].len);
364 406
 		i++;
365 407
 		p = strtok (NULL, "| \t");
366 408
 	}
367 409
 
368
-	if (strcmp (mt_mode.s, "rand") ==0)
369
-	{
370
-		mtmode = mode_random;
410
+	pkg_free(table_name_cpy);
411
+
412
+	*table_names = names;
413
+
414
+	return no_tables;
415
+
416
+}
417
+
418
+/* checks for some missing fields*/
419
+int check_capture_mode ( _capture_mode_data_t * n) {
420
+
421
+
422
+	if (!n->db_url.s || !n->db_url.len){
423
+		LM_ERR("db_url not set\n");
424
+		goto error;
371 425
 	}
372
-	else if (strcmp (mt_mode.s, "round_robin") ==0)
373
-	{
374
-		mtmode = mode_round_robin;
426
+
427
+	if (!n->mtmode ){
428
+		LM_ERR("mt_mode not set\n");
429
+		goto error;
375 430
 	}
376
-	else if (strcmp (mt_mode.s, "hash") == 0)
377
-	{
378
-		mtmode = mode_hash;
431
+	else if (!n->no_tables || !n->table_names){
432
+		LM_ERR("table names not set\n");
433
+		goto error;
379 434
 	}
380
-	else {
381
-		LM_ERR("ERROR: sipcapture: mod_init: multiple tables mode unrecognized\n");
435
+	return 0;
436
+
437
+	error:
438
+	LM_ERR("parsing capture_mode: not all needed parameters are set. Please check again\n");
439
+	return -1;
440
+}
441
+
442
+int capture_mode_set_params (_capture_mode_data_t * n, str * params){
443
+
444
+
445
+	param_t * params_list = NULL;
446
+	param_hooks_t phooks;
447
+	param_t *pit=NULL;
448
+	db_func_t db_funcs;
449
+
450
+	str s;
451
+	LM_DBG("to tokenize: [%.*s]\n", params->len, params->s);
452
+	if ( n == NULL || params == NULL)
382 453
 		return -1;
383
-		
454
+	s = *params;
455
+
456
+	if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0)
457
+		return -1;
458
+	for (pit = params_list; pit; pit=pit->next)
459
+	{
460
+		LM_DBG("parameter is [%.*s]\n",pit->name.len, pit->name.s );
461
+		LM_DBG("parameter value is [%.*s]\n", pit->body.len, pit->body.s);
462
+		if (pit->name.len == 6 && strncmp (pit->name.s, "db_url", pit->name.len)==0){
463
+
464
+			n->db_url.len =pit->body.len;
465
+			n->db_url.s = (char*)pkg_malloc(sizeof(char) * n->db_url.len);
466
+			if (!n->db_url.s){
467
+				LM_ERR("no more pkg memory\n");
468
+				goto error;
469
+			}
470
+			memcpy(n->db_url.s, pit->body.s,n->db_url.len );
471
+
472
+			if (db_bind_mod(&n->db_url, &db_funcs)){
473
+
474
+				LM_ERR("parsing capture_mode: could not bind db funcs for url:[%.*s]\n", n->db_url.len, n->db_url.s);
475
+				goto error;
476
+			}
477
+			n->db_funcs = db_funcs;
478
+
479
+			if (!DB_CAPABILITY(n->db_funcs, DB_CAP_INSERT))
480
+			{
481
+				LM_ERR("parsing capture_mode: database modules does not provide all functions needed"
482
+						" by module\n");
483
+					goto error;
484
+			}
485
+
486
+		}
487
+
488
+		else if (pit->name.len == 10 && strncmp (pit->name.s, "table_name", pit->name.len)==0){
489
+			if ((n->no_tables = parse_table_names(pit->body, &n->table_names))<0){
490
+				LM_ERR("parsing capture_mode: table name parsing failed\n");
491
+				goto error;
492
+			}
493
+
494
+		}
495
+		else if (pit->name.len == 7 && strncmp (pit->name.s, "mt_mode", pit->name.len)==0){
496
+
497
+			if (pit->body.len == 4 && strncmp(pit->body.s, "rand",pit->body.len ) ==0)
498
+			{
499
+				n->mtmode  = mode_random;
500
+			}
501
+			else if (pit->body.len == 11 && strncmp(pit->body.s, "round_robin",pit->body.len ) ==0)
502
+			{
503
+				n->mtmode = mode_round_robin;
504
+			}
505
+			else if (pit->body.len == 4 && strncmp(pit->body.s, "hash", pit->body.len) ==0)
506
+			{
507
+				n->mtmode = mode_hash;
508
+			}
509
+			else {
510
+				LM_ERR("parsing capture_mode: capture mode not recognized: [%.*s]\n", pit->body.len, pit->body.s);
511
+				goto error;
512
+
513
+			}
514
+		}
515
+		else if (pit->name.len == 11 && strncmp (pit->name.s, "hash_source", pit->name.len)==0){
516
+			if ( (n->hash_source = get_hash_source (pit->body.s))  == hs_error)
517
+			{
518
+				LM_ERR("parsing capture_mode: hash source unrecognized: [%.*s]\n", pit->body.len, pit->body.s);
519
+				goto error;
520
+			}
521
+		}
522
+
523
+
524
+	}
525
+	if (n->mtmode == mode_hash && ( n->hash_source == 0 || n->hash_source == hs_error )){
526
+		LM_WARN("Hash mode set, but no hash source provided for [%.*s]. Will consider hashing by call id.\n", n->name.len, n->name.s);
527
+		n->hash_source = hs_call_id;
528
+	}
529
+
530
+	if ( check_capture_mode(n)){
531
+		goto error;
532
+	}
533
+
534
+	return 0;
535
+
536
+error:
537
+	if (n->db_url.s){
538
+		pkg_free(n->db_url.s);
539
+	}
540
+	return -1;
541
+
542
+
543
+
544
+
545
+
546
+}
547
+
548
+void * capture_mode_init(str *name, str * params) {
549
+
550
+	_capture_mode_data_t * n = NULL;
551
+	unsigned int id;
552
+
553
+	if (!name || name->len == 0){
554
+		LM_ERR("capture_mode name is empty\n");
555
+		goto error;
556
+	}
557
+	if (!params || params->len == 0){
558
+		LM_ERR("capture_mode params are empty\n");
559
+		goto error;
560
+	}
561
+	id = core_case_hash(name, 0, 0);
562
+	n = (_capture_mode_data_t *) pkg_malloc(sizeof(_capture_mode_data_t));
563
+	if (!n){
564
+		LM_ERR("no more pkg memory\n");
565
+		goto error;
566
+	}
567
+	memset (n, 0,sizeof(_capture_mode_data_t) );
568
+	n->id = id;
569
+	n->name.len = name->len;
570
+	n->name.s = (char *)pkg_malloc(sizeof(char) * n->name.len);
571
+	if (!n->name.s){
572
+		LM_ERR("no more pkg memory\n");
573
+		goto error;
574
+	}
575
+	memcpy(n->name.s, name->s, n->name.len);
576
+	n->db_con = (db1_con_t *)pkg_malloc(sizeof(db1_con_t));
577
+	if (!n->db_con){
578
+		LM_ERR("no more pkg memory\n");
579
+		goto error;
580
+	}
581
+	n->table_names = (str *)pkg_malloc(sizeof(str));
582
+	if (!n->table_names){
583
+		LM_ERR("no more pkg memory\n");
584
+		goto error;
585
+	}
586
+
587
+
588
+
589
+	if (capture_mode_set_params (n, params)<0){
590
+		LM_ERR("capture mode parsing failed\n");
591
+		goto error;
592
+	}
593
+
594
+	n->next = capture_modes_root;
595
+	capture_modes_root = n;
596
+	return n;
597
+
598
+error:
599
+	if (n->name.s){
600
+		pkg_free(n->name.s);
384 601
 	}
602
+	if (n->db_con){
603
+		pkg_free(n->db_con);
604
+	}
605
+	if (n->table_names){
606
+		pkg_free(n->table_names);
607
+	}
608
+	if (n){
609
+		pkg_free(n);
610
+	}
611
+	return 0;
612
+
613
+}
614
+
615
+/*parse name=>param1=>val1;param2=>val2;..*/
616
+int capture_mode_param(modparam_t type, void *val){
385 617
 
386 618
 
387
-	if ( mtmode == mode_hash && (source = get_hash_source (hash_source.s) ) == hs_error)
619
+	str name;
620
+	str in;
621
+	str tok;
622
+	char * p;
623
+
624
+	in.s = val;
625
+	in.len = strlen(in.s);
626
+	p = in.s;
627
+
628
+	while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
629
+		p++;
630
+	if(p>in.s+in.len || *p=='\0')
631
+		goto error;
632
+	name.s = p;
633
+	while(p < in.s + in.len)
388 634
 	{
389
-		LM_ERR("ERROR: sipcapture: mod_init: hash source unrecognized\n");
390
-		return -1;
635
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
636
+			break;
637
+		p++;
391 638
 	}
392 639
 
393
-	srand(time(NULL));
640
+	if(p>in.s+in.len || *p=='\0')
641
+		goto error;
642
+	name.len = p - name.s;
643
+	if(*p!='=')
644
+	{
645
+		while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
646
+			p++;
647
+		if(p>in.s+in.len || *p=='\0' || *p!='=')
648
+			goto error;
649
+	}
650
+	p++;
651
+	if(*p!='>')
652
+		goto error;
653
+	p++;
654
+	while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
655
+		p++;
656
+	tok.s = p;
657
+	tok.len = in.len + (int)(in.s - p);
394 658
 
659
+	LM_DBG("capture_mode name: [%.*s] data: [%.*s]\n", name.len, name.s, tok.len, tok.s);
660
+	if (!capture_mode_init(&name, &tok)){
661
+		return -1;
662
+	}
395 663
 	return 0;
396 664
 
665
+	error:
666
+		LM_ERR("invalid parameter [%.*s] at [%d]\n", in.len, in.s,
667
+				(int)(p-in.s));
668
+		return -1;
397 669
 }
398 670
 
671
+
672
+
673
+
674
+
675
+
399 676
 /*! \brief Initialize sipcapture module */
400 677
 static int mod_init(void) {
401 678
 
679
+
402 680
 	struct ip_addr *ip = NULL;
681
+	char * def_params = NULL;
403 682
 
404 683
 #ifdef STATISTICS
405
-	/* register statistics */
406
-	if (register_module_stats(exports.name, sipcapture_stats)!=0)
407
-	{
408
-		LM_ERR("failed to register core statistics\n");
409
-		return -1;
410
-	}
684
+	int cnt = 0;
685
+	int i = 0;
686
+	char * stat_name = NULL;
687
+	_capture_mode_data_t * c = NULL;
688
+	int def;
411 689
 #endif
412 690
 
413 691
 	if(register_mi_mod(exports.name, mi_cmds)!=0)
... ...
@@ -468,29 +746,78 @@ static int mod_init(void) {
468 746
 	if(raw_interface.s)
469 747
 		raw_interface.len = strlen(raw_interface.s);     	
470 748
 
471
-	/* Find a database module */
472
-	if (db_bind_mod(&db_url, &db_funcs))
473
-	{
474
-		LM_ERR("unable to bind database module\n");
749
+
750
+	/*Check the table name - if table_name is empty and no capture modes are defined, then error*/
751
+	if(!table_name.len && capture_modes_root == NULL) {
752
+		LM_ERR("ERROR: sipcapture: mod_init: table_name is not defined or empty\n");
475 753
 		return -1;
476 754
 	}
477
-	if (!DB_CAPABILITY(db_funcs, DB_CAP_INSERT))
478
-	{
479
-		LM_ERR("database modules does not provide all functions needed"
480
-				" by module\n");
481
-		return -1;
755
+
756
+
757
+	/*create a default capture mode using the default parameters*/
758
+	def_params = (char *) pkg_malloc(snprintf(NULL, 0, "db_url=%s;table_name=%s;mt_mode=%s;hash_source=%s",db_url.s, table_name.s, mt_mode.s,hash_source.s) + 1);
759
+	sprintf(def_params, "db_url=%s;table_name=%s;mt_mode=%s;hash_source=%s",db_url.s, table_name.s, mt_mode.s,hash_source.s);
760
+
761
+	str def_name,  def_par;
762
+	def_name.s= strdup("default");
763
+	def_name.len = 7;
764
+	def_par.s = def_params;
765
+	def_par.len = strlen (def_params);
766
+
767
+	LM_DBG("def_params is: %s\n", def_params);
768
+
769
+
770
+	if ((capture_def =capture_mode_init(&def_name, &def_par)) == NULL){
771
+		LM_WARN("Default capture mode configuration failed. Suppose sip_capture calls will use other defined capture modes.\n");
482 772
 	}
483 773
 
484
-	/*Check the table name*/
485
-	if(!table_name.len) {	
486
-		LM_ERR("ERROR: sipcapture: mod_init: table_name is not defined or empty\n");
487
-		return -1;
774
+	pkg_free(def_params);
775
+
776
+
777
+#ifdef STATISTICS
778
+
779
+	c = capture_modes_root;
780
+	while (c){
781
+		cnt++;
782
+		c=c->next;
783
+	}
784
+	/*requests and replies for each mode + 1 zero-filled stat_export */
785
+	stat_export_t *stats = (stat_export_t *) shm_malloc(sizeof(stat_export_t) * cnt * 2 + 1 );
786
+
787
+	c = capture_modes_root;
788
+
789
+	while (c){
790
+		/*for the default capture_mode, don't add it's name to the stat name*/
791
+		def = (capture_def && c == capture_def)?1:0;
792
+		stat_name = (char *)shm_malloc(sizeof (char) * snprintf(NULL, 0 , (def)?"captured_requests":"captured_requests[%.*s]", c->name.len, c->name.s) + 1);
793
+		sprintf(stat_name, (def)?"captured_requests":"captured_requests[%.*s]", c->name.len, c->name.s);
794
+		stats[i].name = stat_name;
795
+		stats[i].flags = 0;
796
+		stats[i].stat_pointer = &c->sipcapture_req;
797
+		i++;
798
+		stat_name = (char *)shm_malloc(sizeof (char) * snprintf(NULL, 0 , (def)?"captured_replies":"captured_replies[%.*s]", c->name.len, c->name.s) + 1);
799
+		sprintf(stat_name, (def)?"captured_replies":"captured_replies[%.*s]", c->name.len, c->name.s);
800
+		stats[i].name = stat_name;
801
+		stats[i].flags = 0;
802
+		stats[i].stat_pointer = &c->sipcapture_rpl;
803
+		i++;
804
+		c=c->next;
488 805
 	}
806
+	stats[i].name = 0;
807
+	stats[i].flags = 0;
808
+	stats[i].stat_pointer = 0;
489 809
 
490
-	if (mt_init () <0)
810
+	sipcapture_stats = stats;
811
+
812
+	/* register statistics */
813
+	if (register_module_stats(exports.name, sipcapture_stats)!=0)
491 814
 	{
815
+		LM_ERR("failed to register core statistics\n");
492 816
 		return -1;
493 817
 	}
818
+#endif
819
+
820
+	srand(time(NULL));
494 821
 
495 822
 
496 823
 	if(db_insert_mode) {
... ...
@@ -586,14 +913,42 @@ error:
586 913
 
587 914
 static int sipcapture_fixup(void** param, int param_no)
588 915
 {
589
-        if (param_no == 1) {
916
+
917
+		_capture_mode_data_t *con;
918
+
919
+		str val;
920
+		unsigned int id;
921
+
922
+        if (param_no == 1 ) {
590 923
                 return fixup_var_pve_str_12(param, 1);
591 924
         }
925
+        if (param_no == 2 ){
926
+
927
+			val.s = (char *)*param;
928
+			val.len = strlen((char *)*param);
929
+
930
+
931
+			con = capture_modes_root;
932
+			id = core_case_hash (&val, 0 , 0);
933
+			while (con){
934
+				if (id == con->id && con->name.len == val.len
935
+						&& strncmp(con->name.s, val.s, val.len) == 0){
936
+					*param = (void *)con;
937
+					LM_DBG("found capture mode :[%.*s]\n",con->name.len, con->name.s);
938
+					return 0;
939
+				}
940
+				con = con->next;
941
+			}
942
+
943
+			LM_ERR("no capture mode found\n");
944
+			return -1;
945
+
946
+        }
592 947
         
593 948
         return 0;
594 949
 } 
595 950
    
596
-static int w_sip_capture(struct sip_msg* _m, char* _table, char* s2)
951
+static int w_sip_capture(struct sip_msg* _m, char* _table, _capture_mode_data_t * cm_data, char* s2)
597 952
 {
598 953
         str table = {0};
599 954
         
... ...
@@ -603,7 +958,7 @@ static int w_sip_capture(struct sip_msg* _m, char* _table, char* s2)
603 958
                 return -1;
604 959
         }
605 960
 
606
-        return sip_capture(_m, (table.len>0)?&table:NULL);
961
+        return sip_capture(_m, (table.len>0)?&table:NULL, cm_data );
607 962
 }
608 963
 
609 964
 
... ...
@@ -633,6 +988,9 @@ int extract_host_port(void)
633 988
 
634 989
 static int child_init(int rank)
635 990
 {
991
+
992
+	_capture_mode_data_t * c;
993
+
636 994
 	if (rank == PROC_MAIN && (ipip_capture_on || moni_capture_on)) {
637 995
                 if (init_rawsock_children() < 0) return -1;
638 996
         }
... ...
@@ -640,23 +998,34 @@ static int child_init(int rank)
640 998
 	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
641 999
 		return 0; /* do nothing for the main process */
642 1000
 
643
-	db_con = db_funcs.init(&db_url);
644
-	if (!db_con)
645
-	{
646
-		LM_ERR("unable to connect to database. Please check configuration.\n");
647
-		return -1;
1001
+
1002
+	c = capture_modes_root;
1003
+
1004
+	while (c){
1005
+		if (!c->db_url.s || !c->db_url.len ){
1006
+			LM_ERR("DB URL not set for capture mode:[%.*s]", c->name.len, c->name.s);
1007
+			return -1;
1008
+		}
1009
+		c->db_con = c->db_funcs.init(&c->db_url);
1010
+		if (!c->db_con)
1011
+		{
1012
+			LM_ERR("unable to connect to database [%.*s] from capture_mode param.\n", c->db_url.len, c->db_url.s);
1013
+			return -1;
1014
+		}
1015
+	    if (c->mtmode ==mode_round_robin && rank > 0)
1016
+	    {
1017
+			c->rr_idx = rank % c->no_tables;
1018
+	    }
1019
+		c = c->next;
648 1020
 	}
649
-	
1021
+
1022
+
650 1023
 	heptime = (struct hep_timehdr*)pkg_malloc(sizeof(struct hep_timehdr));
651 1024
         if(heptime==NULL) {
652 1025
                 LM_ERR("no more pkg memory left\n");
653 1026
                 return -1;
654 1027
         }
655 1028
 
656
-    if (mtmode ==mode_round_robin && rank > 0)
657
-    {
658
-		rr_idx = rank % no_tables;
659
-    }
660 1029
 
661 1030
 	return 0;
662 1031
 }
... ...
@@ -687,8 +1056,33 @@ int init_rawsock_children(void)
687 1056
 
688 1057
 static void destroy(void)
689 1058
 {
690
-	if (db_con!=NULL)
691
-		db_funcs.close(db_con);
1059
+	//if (capture_def->db_con!=NULL)
1060
+	//	capture_def->db_funcs.close(capture_def->db_con);
1061
+
1062
+	/*free content from the linked list*/
1063
+	_capture_mode_data_t * c;
1064
+
1065
+	c = capture_modes_root;
1066
+
1067
+	while (c){
1068
+		if (c->name.s){
1069
+			pkg_free(c->name.s);
1070
+		}
1071
+		if (c->db_url.s){
1072
+			pkg_free(c->name.s);
1073
+		}
1074
+		if (c->db_con){
1075
+			c->db_funcs.close(c->db_con);
1076
+			pkg_free(c->db_con);
1077
+		}
1078
+		if (c->table_names){
1079
+			pkg_free(c->table_names);
1080
+		}
1081
+
1082
+		pkg_free(c);
1083
+		c = c->next;
1084
+	}
1085
+
692 1086
 	if (capture_on_flag)
693 1087
 		shm_free(capture_on_flag);
694 1088
 		
... ...
@@ -708,12 +1102,10 @@ static void destroy(void)
708 1102
 		close(raw_sock_desc);
709 1103
 	}
710 1104
 
711
-	if (table_name_cpy){
712
-		pkg_free(table_name_cpy);
713
-	}
714
-	if (table_names){
715
-		pkg_free(table_names);
716
-	}
1105
+
1106
+//	if (table_names){
1107
+//		pkg_free(table_names);
1108
+//	}
717 1109
 }
718 1110
 
719 1111
 static int sip_capture_prepare(sip_msg_t *msg)
... ...
@@ -727,13 +1119,21 @@ static int sip_capture_prepare(sip_msg_t *msg)
727 1119
         return 0;
728 1120
 }
729 1121
 
730
-static int sip_capture_store(struct _sipcapture_object *sco, str *dtable)
1122
+static int sip_capture_store(struct _sipcapture_object *sco, str *dtable, _capture_mode_data_t * cm_data)
731 1123
 {
732 1124
 	db_key_t db_keys[NR_KEYS];
733 1125
 	db_val_t db_vals[NR_KEYS];
734 1126
 
735 1127
 	str tmp;
736 1128
 	int ii = 0;
1129
+	str *table = NULL;
1130
+	_capture_mode_data_t *c = NULL;
1131
+
1132
+	c = (cm_data)? cm_data:capture_def;
1133
+	if (!c){
1134
+		LM_ERR("no connection mode available to store data\n");
1135
+		return -1;
1136
+	}
737 1137
 
738 1138
 	if(sco==NULL)
739 1139
 	{
... ...
@@ -939,36 +1339,47 @@ static int sip_capture_store(struct _sipcapture_object *sco, str *dtable)
939 1339
 
940 1340
 	db_vals[35].val.blob_val = tmp;
941 1341
 
942
-	if (no_tables > 0 ){
943
-		if ( mtmode == mode_hash ){
944
-			ii = hash_func ( sco, source , no_tables);
1342
+	if (dtable){
1343
+		table = dtable;
1344
+	}
1345
+
1346
+	else if (c->no_tables > 0 ){
1347
+
1348
+		if ( c->mtmode == mode_hash ){
1349
+			ii = hash_func ( sco, c->hash_source , c->no_tables);
1350
+			if (ii < 0){
1351
+				LM_ERR("hashing failed\n");
1352
+				return -1;
1353
+			}
945 1354
 			LM_DBG ("hash idx is:%d\n", ii);
946 1355
 		}
947
-		else if (mtmode == mode_random )
1356
+		else if (c->mtmode == mode_random )
948 1357
 		{
949
-			ii = rand() % no_tables;
1358
+			ii = rand() % c->no_tables;
950 1359
 			LM_DBG("rand idx is:%d\n", ii);
951 1360
 		}
952
-		else if (mtmode == mode_round_robin)
1361
+		else if (c->mtmode == mode_round_robin)
953 1362
 		{
954
-			ii = rr_idx;
955
-			rr_idx = (rr_idx +1) % no_tables;
1363
+			ii = c->rr_idx;
1364
+			c->rr_idx = (c->rr_idx +1) % c->no_tables;
956 1365
 			LM_DBG("round robin idx is:%d\n", ii);
957 1366
 		}
1367
+		table = &c->table_names[ii];
958 1368
 	}
959 1369
 
1370
+
960 1371
 	/* check dynamic table */
961
-	LM_DBG("insert into homer table: [%.*s]\n", (dtable)?dtable->len:table_names[ii].len, (dtable)?dtable->s:table_names[ii].s);
962
-	db_funcs.use_table(db_con, (dtable)?dtable:&table_names[ii]);
1372
+	LM_DBG("insert into homer table: [%.*s]\n", table->len, table->s);
1373
+	c->db_funcs.use_table(c->db_con, table);
963 1374
 
964 1375
 	LM_DBG("storing info...\n");
965 1376
 	
966
-	if(db_insert_mode==1 && db_funcs.insert_delayed!=NULL) {
967
-                if (db_funcs.insert_delayed(db_con, db_keys, db_vals, NR_KEYS) < 0) {
1377
+	if(db_insert_mode==1 && c->db_funcs.insert_delayed!=NULL) {
1378
+                if (c->db_funcs.insert_delayed(c->db_con, db_keys, db_vals, NR_KEYS) < 0) {
968 1379
                 	LM_ERR("failed to insert delayed into database\n");
969 1380
                         goto error;
970 1381
                 }
971
-        } else if (db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) {
1382
+        } else if (c->db_funcs.insert(c->db_con, db_keys, db_vals, NR_KEYS) < 0) {
972 1383
 		LM_ERR("failed to insert into database\n");
973 1384
                 goto error;               
974 1385
 	}
... ...
@@ -983,7 +1394,7 @@ error:
983 1394
 	return -1;
984 1395
 }
985 1396
 
986
-static int sip_capture(struct sip_msg *msg, str *_table)
1397
+static int sip_capture(struct sip_msg *msg, str *_table, _capture_mode_data_t * cm_data)
987 1398
 {
988 1399
 	struct _sipcapture_object sco;
989 1400
 	struct sip_uri from, to, contact;
... ...
@@ -1035,7 +1446,7 @@ static int sip_capture(struct sip_msg *msg, str *_table)
1035 1446
 		EMPTY_STR(sco.ruri_user);		
1036 1447
 	}
1037 1448
 	else {		
1038
-		LM_ERR("unknow type [%i]\n", msg->first_line.type);	
1449
+		LM_ERR("unknown type [%i]\n", msg->first_line.type);
1039 1450
 		EMPTY_STR(sco.method);
1040 1451
 		EMPTY_STR(sco.reply_reason);
1041 1452
 		EMPTY_STR(sco.ruri);
... ...
@@ -1285,13 +1696,13 @@ static int sip_capture(struct sip_msg *msg, str *_table)
1285 1696
         
1286 1697
 #ifdef STATISTICS
1287 1698
 	if(msg->first_line.type==SIP_REPLY) {
1288
-		sco.stat = sipcapture_rpl;
1699
+		sco.stat = cm_data->sipcapture_rpl;
1289 1700
 	} else {
1290
-		sco.stat = sipcapture_req;
1701
+		sco.stat = cm_data->sipcapture_req;
1291 1702
 	}
1292 1703
 #endif
1293 1704
 	//LM_DBG("DONE");
1294
-	return sip_capture_store(&sco, _table);
1705
+	return sip_capture_store(&sco, _table, cm_data);
1295 1706
 }
1296 1707
 
1297 1708
 #define capture_is_off(_msg) \