Add a pointer to the start frame of each gop in the gog's tree
[obnox/wireshark/wip.git] / plugins / mate / mate_setup.c
1 /* mate_setup.c
2 * MATE -- Meta Analysis Tracing Engine
3 *
4 * Copyright 2004, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
5 *
6 * $Id$
7 *
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27 #include "mate.h"
28
29 static int* dbg;
30
31 static int dbg_cfg_lvl = 0;
32 static int* dbg_cfg = &dbg_cfg_lvl;
33
34 FILE* dbg_facility;
35
36 typedef gboolean config_action(AVPL* avpl);
37
38 /* the current mate_config */
39 static mate_config* matecfg = NULL;
40
41 /* key: the name of the action
42 value: a pointer to an config_action */
43 static GHashTable* actions = NULL;
44
45 /* aestetics: I like keywords separated from user attributes */
46 static AVPL* all_keywords = NULL;
47
48 /* configuration error */
49 GString* config_error;
50
51 static void report_error(guint8* fmt, ...) {
52         static guint8 error_buffer[DEBUG_BUFFER_SIZE];
53
54         va_list list;
55         
56         va_start( list, fmt );
57         g_vsnprintf(error_buffer,DEBUG_BUFFER_SIZE,fmt,list);
58         va_end( list );
59         
60         g_string_append(config_error,error_buffer);
61         g_string_append_c(config_error,'\n');
62         
63 }
64
65 /* use as:  setting = extract_named_xxx(avpl,keyword,default_value); */
66 static int extract_named_int(AVPL* avpl, guint8* keyword, int value) {
67         AVP* avp = NULL;
68
69         if(( avp = extract_avp_by_name(avpl,keyword) )) {
70                 value = strtol(avp->v,NULL,10);
71         }
72
73         return value;
74 }
75
76 static float extract_named_float(AVPL* avpl, guint8* keyword, float value) {
77         AVP* avp = NULL;
78
79         if(( avp = extract_avp_by_name(avpl,keyword) )) {
80                 value = (float) strtod(avp->v,NULL);
81         }
82
83         return value;
84 }
85
86 static gboolean extract_named_bool(AVPL* avpl, guint8* keyword, gboolean value) {
87         AVP* avp = NULL;
88         if(( avp = extract_avp_by_name(avpl,keyword) )) {
89                 value = ((g_strcasecmp(avp->v,"TRUE") == 0) ? TRUE : FALSE);
90         }
91
92         return value;
93 }
94
95 static guint8* extract_named_str(AVPL* avpl, guint8* keyword, guint8* value) {
96         AVP* avp = NULL;
97
98         if(( avp = extract_avp_by_name(avpl,keyword) )) {
99                 value = avp->v;
100         }
101
102         return value;
103 }
104
105 /* lookups for the string value of the given named attribute from a given hash  */
106 static gpointer lookup_using_index_avp(AVPL* avpl, guint8* keyword, GHashTable* table, guint8** avp_value) {
107         AVP* avp = extract_avp_by_name(avpl,keyword);
108
109         if (avp) {
110                 *avp_value = avp->v;
111                 return g_hash_table_lookup(table,avp->v);
112         } else {
113                 *avp_value = NULL;
114                 return NULL;
115         }
116 }
117
118
119 /* creates and initializes a mate_cfg_item */
120 static mate_cfg_item* new_mate_cfg_item(guint8* name) {
121         mate_cfg_pdu* new = g_malloc(sizeof(mate_cfg_item));
122
123         new->name = g_strdup(name);
124         new->type = MATE_UNK_TYPE;
125         new->transforms = g_ptr_array_new();
126         new->extra = new_avpl(name);
127         new->last_id = 0;
128         new->hfid = -1;
129         new->my_hfids = g_hash_table_new(g_str_hash,g_str_equal);
130         new->items = g_hash_table_new(g_direct_hash,g_direct_equal);
131         new->ett = -1;
132         new->ett_attr = -1;
133         new->ett_times = -1;
134         new->ett_children = -1;
135         
136         new->discard_pdu_attributes = matecfg->discard_pdu_attributes;
137         new->last_to_be_created = matecfg->last_to_be_created;
138         new->hfid_proto = -1;
139         new->hfid_ranges = NULL;
140         new->hfids_attr = NULL;
141         new->drop_pdu = matecfg->drop_pdu;
142         new->criterium_match_mode = AVPL_NO_MATCH;
143         new->criterium = NULL;
144         new->hfid_pdu_rel_time = -1;
145         new->hfid_pdu_time_in_gop = -1;
146
147         new->expiration = -1.0;
148         new->hfid_start_time = -1;
149         new->hfid_stop_time = -1;
150         new->hfid_last_time = -1;
151         
152         new->start = NULL;
153         new->stop = NULL;
154         new->key = NULL;
155         new->show_pdu_tree = matecfg->show_pdu_tree;
156         new->show_times = matecfg->show_times;
157         new->drop_gop = matecfg->drop_gop;
158         new->idle_timeout = -1.0;
159         new->lifetime = -1.0;
160         new->hfid_gop_pdu = -1;
161         new->hfid_gop_num_pdus = -1;
162         new->ett_gog_gop = -1;
163         new->hfid_gog_gopstart = -1;
164         
165         new->gop_index = NULL;
166         new->gog_index = NULL;
167
168         new->gop_as_subtree = FALSE;
169         new->keys = NULL;
170         new->hfid_gog_num_of_gops = -1;
171         new->hfid_gog_gop = -1;
172         
173         return new;
174 }
175
176 /* for cleaning hashes */
177 static gboolean free_both(gpointer k, gpointer v, gpointer p) {
178         g_free(k);
179         if (p) g_free(v);
180         return TRUE;
181 }
182
183 static void delete_mate_cfg_item(mate_cfg_item* cfg, gboolean avp_items_too) {
184
185         g_free(cfg->name);
186
187         if (avp_items_too) {
188                 if (cfg->extra) delete_avpl(cfg->extra,TRUE);
189                 if (cfg->start) delete_avpl(cfg->start,TRUE);
190                 if (cfg->stop)  delete_avpl(cfg->stop,TRUE);
191                 if (cfg->key)  delete_avpl(cfg->key,TRUE);
192                 if (cfg->criterium)  delete_avpl(cfg->criterium,TRUE);
193                 if (cfg->keys) delete_loal(cfg->keys,TRUE,TRUE);
194         }
195
196         if (cfg->transforms) g_ptr_array_free(cfg->transforms,TRUE);
197
198         if (cfg->hfid_ranges)
199                 g_ptr_array_free(cfg->hfid_ranges,TRUE);
200
201         if (cfg->hfids_attr)
202                 g_hash_table_foreach_remove(cfg->hfids_attr,free_both, VALUE_TOO );
203
204 }
205
206 static mate_cfg_pdu* new_pducfg(guint8* name) {
207         mate_cfg_pdu* new = new_mate_cfg_item(name);
208
209         new->type = MATE_PDU_TYPE;
210         new->hfid_ranges = g_ptr_array_new();
211         new->hfids_attr = g_hash_table_new(g_int_hash,g_int_equal);
212
213         g_ptr_array_add(matecfg->pducfglist,(gpointer) new);
214
215         g_hash_table_insert(matecfg->pducfgs,(gpointer) new->name,(gpointer) new);
216
217         return new;
218 }
219
220 static mate_cfg_gop* new_gopcfg(guint8* name) {
221         mate_cfg_gop* new = new_mate_cfg_item(name);
222         
223         new->type = MATE_GOP_TYPE;
224         new->expiration = matecfg->gop_expiration;
225         new->idle_timeout = matecfg->gop_idle_timeout;
226         new->lifetime = matecfg->gop_lifetime;
227         new->show_pdu_tree = matecfg->show_pdu_tree;
228         new->show_times = matecfg->show_times;
229         new->drop_gop = matecfg->drop_gop;
230         
231         g_hash_table_insert(matecfg->gopcfgs,(gpointer) new->name, (gpointer) new);
232
233         new->gop_index = g_hash_table_new(g_str_hash,g_str_equal);
234         new->gog_index = g_hash_table_new(g_str_hash,g_str_equal);
235         
236         return new;
237 }
238
239 static mate_cfg_gog* new_gogcfg(guint8* name) {
240         mate_cfg_gog* new = new_mate_cfg_item(name);
241         new->type = MATE_GOG_TYPE;
242
243         new->keys = new_loal(name);
244         new->expiration = matecfg->gog_expiration;
245         
246         g_hash_table_insert(matecfg->gogcfgs,new->name,new);
247
248         return new;
249 }
250
251 static gboolean free_cfgs(gpointer k _U_, gpointer v, gpointer p) {
252         delete_mate_cfg_item((mate_cfg_item*)v,(gboolean) p);
253         return TRUE;
254 }
255
256 extern void destroy_mate_config(mate_config* mc , gboolean avplib_too) {
257         if (mc->dbg_facility) fclose(mc->dbg_facility);
258         if (mc->mate_lib_path) g_free(mc->mate_lib_path);
259         if (mc->mate_config_file) g_free(mc->mate_config_file);
260         if (mc->mate_attrs_filter) g_string_free(mc->mate_attrs_filter,TRUE);
261         if (mc->mate_protos_filter) g_string_free(mc->mate_protos_filter,TRUE);
262         if (mc->pducfglist) g_ptr_array_free(mc->pducfglist,FALSE);
263
264         if (mc->gogs_by_gopname) {
265                 g_hash_table_destroy(mc->gogs_by_gopname);
266         }
267
268         if (mc->pducfgs) {
269                 g_hash_table_foreach_remove(mc->pducfgs,free_cfgs,(gpointer) avplib_too);
270                 g_hash_table_destroy(mc->pducfgs);
271         }
272
273         if (mc->gopcfgs) {
274                 g_hash_table_foreach_remove(mc->gopcfgs,free_cfgs,(gpointer) avplib_too);
275                 g_hash_table_destroy(mc->gopcfgs);
276         }
277
278         if (mc->gogcfgs) {
279                 g_hash_table_foreach_remove(mc->gogcfgs,free_cfgs,(gpointer) avplib_too);
280                 g_hash_table_destroy(mc->gogcfgs);
281         }
282
283         if (mc->tap_filter)     g_free(mc->tap_filter);
284
285         if (mc->hfrs) g_array_free(mc->hfrs,TRUE);
286         g_free(mc);
287
288 }
289
290 static gboolean mate_load_config(guint8* filename) {
291         LoAL* loal = loal_from_file(filename);
292         AVPL* avpl;
293         config_action* action;
294         guint8* name;
295         
296         /* FIXME: we are leaking the config avpls to avoid unsubscribed strings left arround */ 
297
298         if (loal->len) {
299                 while(( avpl = extract_first_avpl(loal) )) {
300                         dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: current line: %s",avpl->name);
301                         
302                         action = lookup_using_index_avp(avpl, KEYWORD_ACTION, actions,&name);
303                         
304                         if (action) {
305                                 if ( ! action(avpl) ) {
306                                         report_error("MATE: Error on: %s",avpl->name);
307                                         return FALSE;
308                                 }
309                         } else {
310                                 report_error("MATE: action '%s' unknown in: %s",name,avpl->name);
311                                 return FALSE;
312                         }
313                 }
314                 
315                 return TRUE;
316         } else {
317                 report_error("MATE: error reading config file: %s",loal->name);
318                 return FALSE;
319         }
320 }
321
322 static gboolean add_hfid(guint8* what, guint8* how, GHashTable* where) {
323         header_field_info*  hfi = NULL;
324         header_field_info*  first_hfi = NULL;
325         gboolean exists = FALSE;
326         guint8* as;
327         guint8* h;
328         int* ip;
329
330         hfi = proto_registrar_get_byname(what);
331
332         while(hfi) {
333                 first_hfi = hfi;
334                 hfi = hfi->same_name_prev;
335         }
336
337         hfi = first_hfi;
338
339         while (hfi) {
340                 exists = TRUE;
341                 ip = g_malloc(sizeof(int));
342
343                 *ip = hfi->id;
344
345                 if (( as = g_hash_table_lookup(where,ip) )) {
346                         g_free(ip);
347                         if (! g_str_equal(as,how)) {
348                                 report_error("MATE Error: add field to Pdu: attempt to add %s(%i) as %s"
349                                                   " failed: field already added as '%s'",what,hfi->id,how,as);
350                                 return FALSE;
351                         }
352                 } else {
353                         h = g_strdup(how);
354                         g_hash_table_insert(where,ip,h);
355
356
357                         dbg_print (dbg,5,dbg_facility,"add_hfid: added hfid %s(%i) as %s",what,*ip,how);
358                 }
359
360                 hfi = hfi->same_name_next;
361
362         }
363
364         if (! exists) {
365                 report_error("MATE Error: cannot find field %s",what);
366         }
367
368         return exists;
369 }
370
371 static gboolean config_pdu(AVPL* avpl) {
372         guint8* name = NULL;
373         guint8* transport = extract_named_str(avpl,KEYWORD_TRANSPORT,NULL);
374         guint8* proto = extract_named_str(avpl,KEYWORD_PROTO,"no_protocol");
375         mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_NAME,matecfg->pducfgs,&name);
376         header_field_info* hfi;
377         int* hfidp;
378         gchar**  transports;
379         guint i;
380         AVP* attr_avp;
381
382         if (! name ) {
383                 report_error("MATE: PduDef: No Name in: %s",avpl->name);
384                 return FALSE;           
385         }
386         
387         if (! cfg) {
388                 cfg = new_pducfg(name);
389         } else {
390                 report_error("MATE: PduDef: No such PDU: '%s' in: %s",cfg->name,avpl->name);
391                 return FALSE;
392         }
393
394         cfg->last_to_be_created = extract_named_bool(avpl,KEYWORD_STOP,matecfg->last_to_be_created);
395         cfg->discard_pdu_attributes = extract_named_bool(avpl,KEYWORD_DISCARDPDU,matecfg->discard_pdu_attributes);
396         cfg->drop_pdu = extract_named_bool(avpl,KEYWORD_DROPPDU,matecfg->drop_pdu);
397
398         hfi = proto_registrar_get_byname(proto);
399
400         if (hfi) {
401                 cfg->hfid_proto = hfi->id;
402         } else {
403                 report_error("MATE: PduDef: no such proto: '%s' in: %s",proto,avpl->name);
404                 return FALSE;
405         }
406
407         g_string_sprintfa(matecfg->mate_protos_filter,"||%s",proto);
408
409         if ( transport ) {
410
411                 transports = g_strsplit(transport,"/",0);
412
413                 if (transports) {
414                         for (i=0; transports[i]; i++) {
415                                 hfi = proto_registrar_get_byname(transports[i]);
416                                 if (hfi) {
417                                         hfidp = g_malloc(sizeof(int));
418                                         *hfidp = hfi->id;
419                                         g_ptr_array_add(cfg->hfid_ranges,(gpointer)hfidp);
420                                         g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",transports[i]);
421                                 } else {
422                                         report_error("MATE: PduDef: no such proto: '%s' for Transport in: %s",proto,avpl->name);
423                                         g_strfreev(transports);
424                                         return FALSE;
425                                 }
426                         }
427
428                         g_strfreev(transports);
429                 }
430         } else {
431                 report_error("MATE: PduDef: no Transport for '%s' in: %s",cfg->name,avpl->name);
432                 return FALSE;
433         }
434
435         while (( attr_avp = extract_first_avp(avpl) )) {
436                 if ( ! add_hfid(attr_avp->v,attr_avp->n,cfg->hfids_attr) ) {
437                         report_error("MATE: PduDef: failed to set PDU attribute '%s' in: %s",attr_avp->n,avpl->name);
438                         return FALSE;
439                 }
440                 g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",attr_avp->v);
441         }
442
443         return TRUE;
444 }
445
446 static gboolean config_pduextra(AVPL* avpl) {
447         guint8* name;
448         AVP* attr_avp;
449         mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_FOR,matecfg->pducfgs,&name);
450
451         if (! name ) {
452                 report_error("MATE: PduExtra: No For in: %s",avpl->name);
453                 return FALSE;           
454         }
455
456         if (! cfg) {
457                 report_error("MATE: PduExtra: no such Pdu '%s' in: %s",name,avpl->name);
458                 return FALSE;
459         }
460
461         cfg->last_to_be_created = extract_named_bool(avpl,KEYWORD_STOP,cfg->last_to_be_created);
462         cfg->discard_pdu_attributes = extract_named_bool(avpl,KEYWORD_DISCARDPDU,cfg->discard_pdu_attributes);
463         cfg->drop_pdu = extract_named_bool(avpl,KEYWORD_DROPPDU,cfg->drop_pdu);
464
465         while (( attr_avp = extract_first_avp(avpl) )) {
466                 if ( ! add_hfid(attr_avp->v,attr_avp->n,cfg->hfids_attr) ) {
467                         report_error("MATE: PduExtra: failed to set attr '%s' in: %s",attr_avp->n,avpl->name);
468                         delete_avp(attr_avp);
469                         return FALSE;
470                 }
471                 g_string_sprintfa(matecfg->mate_attrs_filter, "||%s",attr_avp->v);
472         }
473
474         delete_avpl(avpl,TRUE);
475         return TRUE;
476
477 }
478
479
480 static gboolean config_pducriteria(AVPL* avpl) {
481         guint8* name;
482         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->pducfgs,&name);
483         guint8* match = extract_named_str(avpl, KEYWORD_MATCH, NULL);
484         avpl_match_mode match_mode = AVPL_STRICT;
485         guint8* mode = extract_named_str(avpl, KEYWORD_MODE, NULL);
486
487         if (! name ) {
488                 report_error("MATE: PduCriteria: No For in: %s",avpl->name);
489                 return FALSE;           
490         }
491         
492         if (!cfg) {
493                 report_error("MATE: PduCriteria: Pdu '%s' does not exist in: %s",name,avpl->name);
494                 return FALSE;
495         }
496
497         if ( mode ) {
498                 if ( g_strcasecmp(mode,KEYWORD_ACCEPT) == 0 ) {
499                         mode = matecfg->accept;
500                 } else if ( g_strcasecmp(mode,KEYWORD_REJECT) == 0 ) {
501                         mode = matecfg->reject;
502                 } else {
503                         report_error("MATE: PduCriteria: no such criteria mode: '%s' in %s",mode,avpl->name);
504                         return FALSE;
505                 }
506         } else {
507                 mode = matecfg->accept;
508         }
509
510         rename_avpl(avpl,mode);
511
512         if ( match ) {
513                 if ( g_strcasecmp(match,KEYWORD_LOOSE) == 0 ) {
514                         match_mode = AVPL_LOOSE;
515                 } else if ( g_strcasecmp(match,KEYWORD_EVERY) == 0 ) {
516                         match_mode = AVPL_EVERY;
517                 } else if ( g_strcasecmp(match,KEYWORD_STRICT) == 0 ) {
518                         match_mode = AVPL_STRICT;
519                 } else {
520                         report_error("MATE: PduCriteria: Config error: no such match mode '%s' in: %s",match,avpl->name);
521                         return FALSE;
522                 }
523         }
524
525         cfg->criterium_match_mode = match_mode;
526
527         if (cfg->criterium) {
528                 /* FEATURE: more criteria */
529                 report_error("MATE: PduCriteria: PduCriteria alredy exists for '%s' in: %s",name,avpl->name);
530                 return FALSE;
531         }
532
533
534         cfg->criterium = avpl;
535
536         return TRUE;
537 }
538
539
540 static gboolean config_include(AVPL* avpl) {
541         guint8* filename = extract_named_str(avpl,KEYWORD_FILENAME,NULL);
542         guint8* lib = extract_named_str(avpl,KEYWORD_LIB,NULL);
543
544         if ( ! filename && ! lib ) {
545                 report_error("MATE: Include: no Filename or Lib given in: %s",avpl->name);
546                 return FALSE;
547         }
548
549         if ( filename && lib ) {
550                 report_error("MATE: Include: use either Filename or Lib, not both. in: %s",avpl->name);
551                 return FALSE;
552         }
553
554         if (lib) {
555                 filename = g_strdup_printf("%s%s.mate",matecfg->mate_lib_path,lib);
556         }
557
558         /* FIXME: stop recursion */
559         if ( ! mate_load_config(filename) ) {
560                 report_error("MATE: Include: Error Loading '%s' in: %s",filename,avpl->name);
561                 if (lib) g_free(filename);
562                 return FALSE;
563         }
564
565         if (lib) g_free(filename);
566
567         return TRUE;
568 }
569
570
571 static gboolean config_settings(AVPL*avpl) {
572         AVP* avp;
573
574 #ifdef _AVP_DEBUGGING
575         int debug_avp = 0;
576         int dbg_avp = 0;
577         int dbg_avp_op = 0;
578         int dbg_avpl = 0;
579         int dbg_avpl_op = 0;
580 #endif
581
582
583         matecfg->gog_expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration);
584         matecfg->gop_expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,matecfg->gop_expiration);
585         matecfg->gop_idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,matecfg->gop_idle_timeout);
586         matecfg->gop_lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,matecfg->gop_lifetime);
587         matecfg->discard_pdu_attributes = extract_named_bool(avpl, KEYWORD_DISCARDPDU,matecfg->discard_pdu_attributes);
588         matecfg->drop_pdu = extract_named_bool(avpl, KEYWORD_DROPPDU,matecfg->drop_pdu);
589         matecfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,matecfg->drop_gop);
590         matecfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE,matecfg->show_pdu_tree);
591         matecfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_times);
592
593         if(( avp = extract_avp_by_name(avpl,KEYWORD_DEBUGFILENAME) )) {
594                 matecfg->dbg_facility = dbg_facility = fopen(avp->v,"w");
595                 delete_avp(avp);
596                 avp = NULL;
597         }
598
599         matecfg->dbg_lvl = extract_named_int(avpl, KEYWORD_DBG_GENERAL,0);
600         matecfg->dbg_cfg_lvl = extract_named_int(avpl, KEYWORD_DBG_CFG,0);
601         matecfg->dbg_gop_lvl = extract_named_int(avpl, KEYWORD_DBG_PDU,0);
602         matecfg->dbg_gop_lvl = extract_named_int(avpl, KEYWORD_DBG_GOP,0);
603         matecfg->dbg_gog_lvl = extract_named_int(avpl, KEYWORD_DBG_GOG,0);
604
605 #ifdef _AVP_DEBUGGING
606          setup_avp_debug(dbg_facility,
607                                          extract_named_int(avpl, KEYWORD_DBG_AVPLIB,0),
608                                          extract_named_int(avpl, KEYWORD_DBG_AVP,0),
609                                          extract_named_int(avpl, KEYWORD_DBG_AVP_OP,0),
610                                          extract_named_int(avpl, KEYWORD_DBG_AVPL,0),
611                                          extract_named_int(avpl, KEYWORD_DBG_AVPL_OP,0));
612 #endif
613
614         dbg_cfg_lvl = matecfg->dbg_cfg_lvl;
615
616         return TRUE;
617 }
618
619 static gboolean config_transform(AVPL* avpl) {
620         guint8* name = extract_named_str(avpl, KEYWORD_NAME, NULL);
621         guint8* match = extract_named_str(avpl, KEYWORD_MATCH, NULL);
622         guint8* mode = extract_named_str(avpl, KEYWORD_MODE, NULL);
623         avpl_match_mode match_mode;
624         avpl_replace_mode replace_mode;
625         AVPL_Transf* t;
626         AVPL_Transf* last;
627
628         if ( match ) {
629                 if ( g_strcasecmp(match,KEYWORD_LOOSE) == 0 ) {
630                         match_mode = AVPL_LOOSE;
631                 } else if ( g_strcasecmp(match,KEYWORD_EVERY) == 0 ) {
632                         match_mode = AVPL_EVERY;
633                 } else if ( g_strcasecmp(match,KEYWORD_STRICT) == 0 ) {
634                         match_mode = AVPL_STRICT;
635                 } else {
636                         report_error("MATE: Transform: no such match mode: '%s' in: %s",match,avpl->name);
637                         return FALSE;
638                 }
639         } else {
640                 match_mode = matecfg->match_mode;
641         }
642
643         if ( mode ) {
644                 if ( g_strcasecmp(mode,KEYWORD_INSERT) == 0 ) {
645                         replace_mode = AVPL_INSERT;
646                 } else if ( g_strcasecmp(mode,KEYWORD_REPLACE) == 0 ) {
647                         replace_mode = AVPL_REPLACE;
648                 } else {
649                         report_error("MATE: Transform: no such replace mode: '%s' in: %s",mode,avpl->name);
650                         return FALSE;
651                 }
652
653         } else {
654                 replace_mode = matecfg->replace_mode;
655         }
656
657         if (! name) {
658                 report_error("MATE: Transform: no Name in: %s",avpl->name);
659                 return FALSE;
660         }
661
662         t = new_avpl_transform(name,avpl, match_mode, replace_mode);
663
664         if (( last = g_hash_table_lookup(matecfg->transfs,name) )) {
665                 while (last->next) last = last->next;
666                 last->next = t;
667         } else {
668                 g_hash_table_insert(matecfg->transfs,t->name,t);
669         }
670
671         return TRUE;
672 }
673
674 static gboolean config_xxx_transform(AVPL* avpl, GHashTable* hash, guint8* keyword) {
675         guint8* cfg_name;
676         guint8* name;
677         AVPL_Transf* transf = lookup_using_index_avp(avpl,KEYWORD_NAME,matecfg->transfs,&name);
678         mate_cfg_pdu* cfg = lookup_using_index_avp(avpl,KEYWORD_FOR,hash,&cfg_name);;
679         
680         if (! name ) {
681                 report_error("MATE: %s: no Name in: %s",keyword,avpl->name);
682                 return FALSE;
683         }
684
685         if (! cfg_name ) {
686                 report_error("MATE: %s: no For in: %s",keyword,avpl->name);
687                 return FALSE;
688         }
689
690         if (! cfg ) {
691                 report_error("MATE: %s: '%s' doesn't exist in: %s",keyword,cfg_name,avpl->name);
692                 return FALSE;
693         }
694
695         if (!transf) {
696                 report_error("MATE: %s: Transform '%s' doesn't exist in: %s",keyword,name,avpl->name);
697                 return FALSE;
698         }
699
700         g_ptr_array_add(cfg->transforms,transf);
701
702         return TRUE;
703 }
704
705 static gboolean config_pdu_transform(AVPL* avpl) {
706         return config_xxx_transform(avpl, matecfg->pducfgs, KEYWORD_PDUTRANSFORM);
707 }
708
709 static gboolean config_gop_transform(AVPL* avpl) {
710         return config_xxx_transform(avpl, matecfg->gopcfgs, KEYWORD_GOPTRANSFORM);
711 }
712
713 static gboolean config_gog_transform(AVPL* avpl) {
714         return config_xxx_transform(avpl, matecfg->gogcfgs, KEYWORD_GOPTRANSFORM);
715 }
716
717 static gboolean config_gop(AVPL* avpl) {
718         guint8* name = NULL;
719         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_NAME,matecfg->gopcfgs,&name);
720         guint8* on = extract_named_str(avpl,KEYWORD_ON,NULL);
721
722         if (! name ) {
723                 report_error("MATE: GopDef: no Name in: %s",avpl->name);
724                 return FALSE;
725         }
726         
727         if (!cfg) {
728                 cfg = new_gopcfg(name);
729         } else {
730                 report_error("MATE: GopDef: Gop '%s' exists already in: %s",name,avpl->name);
731                 return FALSE;
732         }
733
734         if (! on ) {
735                 report_error("MATE: GopDef: no On in: %s",avpl->name);
736                 return FALSE;
737         }
738         
739         if (g_hash_table_lookup(matecfg->pducfgs,on) == NULL ) {
740                 report_error("MATE: GopDef: Pdu '%s' does not exist in: %s",on,avpl->name);
741                 return FALSE;           
742         }
743
744         if (g_hash_table_lookup(matecfg->gops_by_pduname,on) ) {
745                 report_error("MATE: GopDef: Gop for Pdu '%s' exists already in: %s",on,avpl->name);
746                 return FALSE;
747         } else {
748                 g_hash_table_insert(matecfg->gops_by_pduname,on,cfg);
749         }
750
751         cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,matecfg->drop_gop);
752         cfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE, matecfg->show_pdu_tree);
753         cfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_times);
754         cfg->expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,matecfg->gop_expiration);
755         cfg->idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,matecfg->gop_idle_timeout);
756         cfg->lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,matecfg->gop_lifetime);
757         
758         cfg->key = avpl;
759
760         return TRUE;
761 }
762
763 static gboolean config_start(AVPL* avpl) {
764         guint8* name;
765         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
766
767         if (! name ) {
768                 report_error("MATE: GopStart: no For in: %s",avpl->name);
769                 return FALSE;
770         }
771         
772         if (!cfg) {
773                 report_error("MATE: GopStart: Gop '%s' doesn't exist in: %s",name,avpl->name);
774                 return FALSE;
775         }
776
777         if (cfg->start) {
778                 /* FEATURE: more start conditions */
779                 report_error("MATE: GopStart: GopStart for '%s' exists already in: %s",name,avpl->name);
780                 return FALSE;
781         }
782
783         cfg->start = avpl;
784
785         return TRUE;
786 }
787
788 static gboolean config_stop(AVPL* avpl) {
789         guint8* name;
790         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
791         
792         if (! name ) {
793                 report_error("MATE: GopStop: no For in: %s",avpl->name);
794                 return FALSE;
795         }
796         
797         if (!cfg) {
798                 report_error("MATE: GopStop: Gop '%s' doesn't exist in: %s",name,avpl->name);
799                 return FALSE;
800         }
801
802         if (cfg->stop) {
803                 report_error("MATE: GopStop: GopStop alredy exists for '%s' in: %s",name,avpl->name);
804                 return FALSE;
805         }
806
807         cfg->stop = avpl;
808
809         return TRUE;
810 }
811
812 static gboolean config_gopextra(AVPL* avpl) {
813         guint8* name;
814         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
815
816         if (! name ) {
817                 report_error("MATE: GopExtra: no For in: %s",avpl->name);
818                 return FALSE;
819         }
820         
821         if (!cfg) {
822                 report_error("MATE: GopExtra: Gop '%s' does not exist in: %s",name,avpl->name);
823                 return FALSE;
824         }
825
826         cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,cfg->drop_gop);
827         cfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE, cfg->show_pdu_tree);
828         cfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,cfg->show_times);
829         cfg->expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,cfg->expiration);
830         cfg->idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,cfg->idle_timeout);
831         cfg->lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,cfg->lifetime);
832         
833         merge_avpl(cfg->extra,avpl,TRUE);
834
835         return TRUE;
836 }
837
838 static gboolean config_gog(AVPL* avpl) {
839         guint8* name = extract_named_str(avpl, KEYWORD_NAME,NULL);
840         mate_cfg_gog* cfg = NULL;
841
842         if (! name ) {
843                 report_error("MATE: GogDef: no Name in: %s",avpl->name);
844                 return FALSE;
845         }
846         
847         if ( g_hash_table_lookup(matecfg->gogcfgs,name) ) {
848                 report_error("MATE: GogDef: Gog '%s' exists already in: %s",name,avpl->name);
849                 return FALSE;
850         }
851
852         cfg = new_gogcfg(name);
853
854         cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration);
855         cfg->gop_as_subtree = extract_named_bool(avpl, KEYWORD_GOPTREE,matecfg->gop_as_subtree);
856         
857         return TRUE;
858 }
859
860 static gboolean config_gogkey(AVPL* avpl) {
861         guint8* name;
862         mate_cfg_gog* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gogcfgs,&name);
863         AVPL* reverse_avpl;
864         LoAL* gogkeys;
865         guint8* on = extract_named_str(avpl,KEYWORD_ON,NULL);
866
867         if ( ! name || ! cfg ) {
868                 if ( ! name )
869                         report_error("MATE: GogKey: no For in %s",avpl->name);
870                 else
871                         report_error("MATE: GogKey: no such Gop '%s' in %s",name,avpl->name);
872
873                 return FALSE;
874         }
875
876         if (! on ) {
877                 report_error("MATE: GogKey: no On in %s",avpl->name);
878                 return FALSE;
879         }
880
881         rename_avpl(avpl,name);
882
883         gogkeys = (LoAL*) g_hash_table_lookup(matecfg->gogs_by_gopname,on);
884
885         if (! gogkeys) {
886                 gogkeys = new_loal("straight");
887                 g_hash_table_insert(matecfg->gogs_by_gopname,g_strdup(on),gogkeys);
888         }
889
890         loal_append(gogkeys,avpl);
891
892         reverse_avpl = new_avpl_from_avpl(on,avpl,TRUE);
893
894         loal_append(cfg->keys,reverse_avpl);
895
896         return TRUE;
897 }
898
899 static gboolean config_gogextra(AVPL* avpl) {
900         guint8* name;
901         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gogcfgs,&name);
902
903         if ( ! name || ! cfg ) {
904                 if ( ! name )
905                         report_error("MATE: GogExtra: no Name in %s",avpl->name);
906                 else
907                         report_error("MATE: GogExtra: no such Gop '%s' in %s",name,avpl->name);
908
909                 return FALSE;
910         }
911
912         cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,cfg->expiration);
913         cfg->gop_as_subtree = extract_named_bool(avpl, KEYWORD_GOPTREE,cfg->gop_as_subtree);
914
915         merge_avpl(cfg->extra,avpl,TRUE);
916
917         return TRUE;
918 }
919
920 #define true_false_str(v) ((v) ? "TRUE" : "FALSE")
921
922 static void print_xxx_transforms(mate_cfg_item* cfg) {
923         guint8* tr_name;
924         guint8* cfg_name;
925         guint i;
926
927         switch (cfg->type) {
928                 case MATE_PDU_TYPE:
929                         cfg_name = "PduTransform";
930                         break;
931                 case MATE_GOP_TYPE:
932                         cfg_name = "GopTransform";
933                         break;
934                 case MATE_GOG_TYPE:
935                         cfg_name = "GogTransform";
936                         break;
937                 default:
938                         cfg_name = "UnknownTransform";
939                         break;
940         }
941
942         for (i=0; i < cfg->transforms->len; i++) {
943                 tr_name = ((AVPL_Transf*) g_ptr_array_index(cfg->transforms,i))->name;
944                 dbg_print (dbg_cfg,0,dbg_facility,"Action=%s; For=%s; Name=%s;",cfg_name,cfg->name,tr_name);
945         }
946
947 }
948
949 static void print_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
950         mate_cfg_gop* cfg = (mate_cfg_gop*) v;
951         guint8* avplstr = NULL;
952         void* cookie = NULL;
953         AVPL* avpl;
954
955         dbg_print (dbg_cfg,0,dbg_facility,"Action=GogDef; Name=%s; Expiration=%f;",cfg->name,cfg->expiration);
956
957         if (cfg->keys) {
958                 while (( avpl = get_next_avpl(cfg->keys,&cookie) )) {
959                         avplstr = avpl_to_str(avpl);
960                         dbg_print (dbg_cfg,0,dbg_facility,"Action=GogKey; For=%s; On=%s; %s",cfg->name,avpl->name,avplstr);
961                         g_free(avplstr);
962                 }
963         }
964
965         if (cfg->extra) {
966                 avplstr = avpl_to_str(cfg->extra);
967                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GogExtra; For=%s; %s",cfg->name,avplstr);
968                 g_free(avplstr);
969         }
970
971         print_xxx_transforms(cfg);
972
973 }
974
975
976
977 static void print_gop_config(gpointer k _U_ , gpointer v, gpointer p _U_) {
978         mate_cfg_gop* cfg = (mate_cfg_gop*) v;
979         guint8* avplstr = NULL;
980         guint8* show_pdu_tree;
981         GString* gopdef;
982
983         gopdef = g_string_new("Action=GopDef; ");
984
985         show_pdu_tree = cfg->show_pdu_tree ? "TRUE" : "FALSE";
986         g_string_sprintfa(gopdef,"Name=%s; ShowPduTree=%s; ShowGopTimes=%s; "
987                                           "GopExpiration=%f; GopIdleTimeout=%f GopLifetime=%f;",
988                                           cfg->name,show_pdu_tree,true_false_str(cfg->show_times),
989                                           cfg->expiration,cfg->idle_timeout,cfg->lifetime);
990
991         if (cfg->key) {
992                 avplstr = avpl_to_str(cfg->key);
993                 g_string_sprintfa(gopdef," %s",avplstr);
994                 g_free(avplstr);
995         }
996
997         dbg_print (dbg_cfg,0,dbg_facility,"%s",gopdef->str);
998
999
1000         if (cfg->start) {
1001                 avplstr = avpl_to_str(cfg->start);
1002                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStart; For=%s; %s",cfg->name,avplstr);
1003                 g_free(avplstr);
1004         }
1005
1006         if (cfg->stop) {
1007                 avplstr = avpl_to_str(cfg->stop);
1008                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStop; For=%s; %s",cfg->name,avplstr);
1009                 g_free(avplstr);
1010         }
1011
1012         if (cfg->extra) {
1013                 avplstr = avpl_to_str(cfg->extra);
1014                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GopExtra; For=%s;  %s",cfg->name,avplstr);
1015                 g_free(avplstr);
1016         }
1017
1018         print_xxx_transforms(cfg);
1019
1020         g_string_free(gopdef,TRUE);
1021
1022 }
1023
1024 static guint8* my_protoname(int proto_id) {
1025         if (proto_id) {
1026                 return proto_registrar_get_abbrev(proto_id);
1027         } else {
1028                 return "*";
1029         }
1030 }
1031
1032 static void print_hfid_hash(gpointer k, gpointer v, gpointer p _U_) {
1033         g_string_sprintfa((GString*)p," %s=%s;",(guint8*)v,my_protoname(*(int*)k));
1034 }
1035
1036
1037 static void print_transforms(gpointer k, gpointer v, gpointer p _U_) {
1038         AVPL_Transf* t = NULL;
1039         guint8* match;
1040         guint8* mode;
1041         guint8* match_s;
1042         guint8* replace_s;
1043
1044         for (t = v; t; t = t->next) {
1045                 match_s =  avpl_to_str(t->match);
1046                 replace_s = avpl_to_dotstr(t->replace);
1047
1048                 switch (t->match_mode) {
1049                         case AVPL_STRICT:
1050                                 match = "Strict";
1051                                 break;
1052                         case AVPL_LOOSE:
1053                                 match = "Loose";
1054                                 break;
1055                         case AVPL_EVERY:
1056                                 match = "Every";
1057                                 break;
1058                         default:
1059                                 match = "None";
1060                                 break;
1061                 }
1062
1063                 switch (t->replace_mode) {
1064                         case AVPL_INSERT:
1065                                 mode = "Insert";
1066                                 break;
1067                         case AVPL_REPLACE:
1068                                 mode = "Replace";
1069                                 break;
1070                         default:
1071                                 mode = "None";
1072                                 break;
1073                 }
1074
1075                 dbg_print (dbg,0,dbg_facility,"\tAction=Transform; Name=%s; Match=%s; Mode=%s; %s %s",(guint8*) k,match,mode,match_s,replace_s);
1076
1077                 g_free(match_s);
1078                 g_free(replace_s);
1079         }
1080 }
1081
1082 static void print_pdu_config(mate_cfg_pdu* cfg) {
1083         guint i;
1084         int hfid;
1085         guint8* discard;
1086         guint8* stop;
1087         guint8* criterium_match = NULL;
1088         guint8* criterium;
1089         GString* s = g_string_new("Action=PduDef; ");
1090
1091         discard = cfg->discard_pdu_attributes ? "TRUE": "FALSE";
1092         stop = cfg->last_to_be_created ? "TRUE" : "FALSE";
1093
1094         g_string_sprintfa(s, "Name=%s; Proto=%s; DiscartAttribs=%s; Stop=%s;  Transport=",
1095                                           cfg->name,my_protoname(cfg->hfid_proto),discard,stop);
1096
1097         for (i = 0; i < cfg->hfid_ranges->len; i++) {
1098                 hfid = *((int*) g_ptr_array_index(cfg->hfid_ranges,i));
1099                 g_string_sprintfa(s,"%s/",my_protoname(hfid));
1100         }
1101
1102         *(s->str + s->len - 1) = ';';
1103
1104         g_hash_table_foreach(cfg->hfids_attr,print_hfid_hash,s);
1105
1106         dbg_print(dbg_cfg,0,dbg_facility,"%s",s->str);
1107
1108         if (cfg->criterium) {
1109                 switch(cfg->criterium_match_mode) {
1110                         case AVPL_NO_MATCH:
1111                                 criterium_match = "None";
1112                                 break;
1113                         case AVPL_STRICT:
1114                                 criterium_match = "Strict";
1115                                 break;
1116                         case AVPL_LOOSE:
1117                                 criterium_match = "Loose";
1118                                 break;
1119                         case AVPL_EVERY:
1120                                 criterium_match = "Every";
1121                                 break;
1122                 }
1123
1124                 criterium = avpl_to_str(cfg->criterium);
1125
1126                 dbg_print(dbg_cfg,0,dbg_facility,
1127                                   "Action=PduCriteria; For=%s; Match=%s; Mode=%s;  %s",
1128                                   cfg->name,criterium_match,cfg->criterium->name,criterium);
1129
1130                 g_free(criterium);
1131         }
1132
1133         print_xxx_transforms(cfg);
1134
1135         g_string_free(s,TRUE);
1136 }
1137
1138
1139
1140 static void print_gogs_by_gopname(gpointer k, gpointer v, gpointer p _U_) {
1141         void* cookie = NULL;
1142         guint8* str = NULL;
1143         AVPL* avpl;
1144
1145         while(( avpl = get_next_avpl((LoAL*)v,&cookie) )) {
1146                 str = avpl_to_str(avpl);
1147                 dbg_print(dbg_cfg,0,dbg_facility,"Gop=%s; Gog=%s; --> %s",(guint8*)k,avpl->name,str);
1148                 g_free(str);
1149         }
1150
1151 }
1152
1153 static void print_gops_by_pduname(gpointer k, gpointer v, gpointer p _U_) {
1154         dbg_print(dbg_cfg,0,dbg_facility,
1155                           "PduName=%s; GopName=%s;", (guint8*)k,((mate_cfg_gop*)v)->name);
1156 }
1157
1158 static void print_config(void) {
1159         guint i;
1160
1161         /* FIXME: print the settings */
1162
1163         dbg_print(dbg_cfg,0,dbg_facility,"###########################"
1164                           " CURRENT CONFIGURATION " "###########################");
1165
1166         g_hash_table_foreach(matecfg->transfs,print_transforms,NULL);
1167
1168         for (i=0; i<matecfg->pducfglist->len; i++) {
1169                 print_pdu_config((mate_cfg_pdu*) g_ptr_array_index(matecfg->pducfglist,i));
1170         }
1171
1172         g_hash_table_foreach(matecfg->gopcfgs,print_gop_config,NULL);
1173         g_hash_table_foreach(matecfg->gogcfgs,print_gog_config,NULL);
1174
1175         dbg_print(dbg_cfg,0,dbg_facility,"###########################"
1176                           " END OF CURRENT CONFIGURATION " "###########################");
1177
1178         if (*dbg_cfg > 1) {
1179                 dbg_print(dbg_cfg,0,dbg_facility,"******* Config Hashes");
1180                 dbg_print(dbg_cfg,0,dbg_facility,"*** Gops by PduName");
1181                 g_hash_table_foreach(matecfg->gops_by_pduname,print_gops_by_pduname,NULL);
1182                 dbg_print(dbg_cfg,0,dbg_facility,"*** GogKeys by GopName");
1183                 g_hash_table_foreach(matecfg->gogs_by_gopname,print_gogs_by_gopname,NULL);
1184         }
1185 }
1186
1187
1188 static void new_attr_hfri(mate_cfg_item* cfg, guint8* name) {
1189         int* p_id = g_malloc(sizeof(int));
1190
1191         hf_register_info hfri;
1192
1193         memset(&hfri, 0, sizeof hfri);
1194         hfri.p_id = p_id;
1195         hfri.hfinfo.name = g_strdup_printf("%s",name);
1196         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.%s",cfg->name,name);
1197         hfri.hfinfo.type = FT_STRING;
1198         hfri.hfinfo.display = BASE_NONE;
1199         hfri.hfinfo.strings = NULL;
1200         hfri.hfinfo.bitmask = 0;
1201         hfri.hfinfo.blurb = g_strdup_printf("%s attribute of %s",name,cfg->name);
1202
1203         *p_id = -1;
1204         g_hash_table_insert(cfg->my_hfids,name,p_id);
1205         g_array_append_val(matecfg->hfrs,hfri);
1206
1207 }
1208
1209 static void analyze_pdu_hfids(gpointer k _U_, gpointer v, gpointer p) {
1210         new_attr_hfri((mate_cfg_pdu*) p,(guint8*) v);
1211 }
1212
1213 static void analyze_transform_hfrs(mate_cfg_item* cfg) {
1214         guint i;
1215         void* cookie = NULL;
1216         AVPL_Transf* t;
1217         AVP* avp;
1218
1219         for (i=0; i < cfg->transforms->len;i++) {
1220                 for (t = g_ptr_array_index(cfg->transforms,i); t; t=t->next ) {
1221                         cookie = NULL;
1222                         while(( avp = get_next_avp(t->replace,&cookie) )) {
1223                                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1224                                         new_attr_hfri(cfg,avp->n);
1225                                 }
1226                         }
1227                 }
1228         }
1229 }
1230
1231 static void analyze_pdu_config(mate_cfg_pdu* cfg) {
1232         hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
1233         gint* ett;
1234
1235         hfri.p_id = &(cfg->hfid);
1236         hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
1237         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
1238         hfri.hfinfo.blurb = g_strdup_printf("%s id",cfg->name);
1239         hfri.hfinfo.type = FT_UINT32;
1240         hfri.hfinfo.display = BASE_DEC;
1241
1242         g_array_append_val(matecfg->hfrs,hfri);
1243         
1244         hfri.p_id = &(cfg->hfid_pdu_rel_time);
1245         hfri.hfinfo.name = g_strdup_printf("%s time",cfg->name);
1246         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.RelativeTime",cfg->name);
1247         hfri.hfinfo.type = FT_FLOAT;
1248         hfri.hfinfo.display = BASE_DEC;
1249         hfri.hfinfo.blurb = "Seconds passed since the start of capture";
1250         
1251         g_array_append_val(matecfg->hfrs,hfri);
1252         
1253         hfri.p_id = &(cfg->hfid_pdu_time_in_gop);
1254         hfri.hfinfo.name = g_strdup_printf("%s time since begining of Gop",cfg->name);
1255         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.TimeInGop",cfg->name);
1256         hfri.hfinfo.type = FT_FLOAT;
1257         hfri.hfinfo.display = BASE_DEC;
1258         hfri.hfinfo.blurb = "Seconds passed since the start of the GOP";
1259         
1260         g_array_append_val(matecfg->hfrs,hfri);
1261         
1262         g_hash_table_foreach(cfg->hfids_attr,analyze_pdu_hfids,cfg);
1263
1264         ett = &cfg->ett;
1265         g_array_append_val(matecfg->ett,ett);
1266
1267         ett = &cfg->ett_attr;
1268         g_array_append_val(matecfg->ett,ett);
1269
1270         analyze_transform_hfrs(cfg);
1271 }
1272
1273 static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) {
1274         mate_cfg_gop* cfg = v;
1275         void* cookie = NULL;
1276         AVP* avp;
1277         gint* ett;
1278         hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
1279
1280         hfri.p_id = &(cfg->hfid);
1281         hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
1282         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
1283         hfri.hfinfo.blurb = g_strdup_printf("%s id",cfg->name);
1284         hfri.hfinfo.type = FT_UINT32;
1285         hfri.hfinfo.display = BASE_DEC;
1286
1287         g_array_append_val(matecfg->hfrs,hfri);
1288
1289         hfri.p_id = &(cfg->hfid_start_time);
1290         hfri.hfinfo.name = g_strdup_printf("%s start time",cfg->name);
1291         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.StartTime",cfg->name);
1292         hfri.hfinfo.type = FT_FLOAT;
1293         hfri.hfinfo.display = BASE_DEC;
1294         hfri.hfinfo.blurb = g_strdup_printf("Seconds passed since the begining of caputre to the start of this %s",cfg->name);
1295
1296         g_array_append_val(matecfg->hfrs,hfri);
1297
1298         hfri.p_id = &(cfg->hfid_stop_time);
1299         hfri.hfinfo.name = g_strdup_printf("%s hold time",cfg->name);
1300         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Time",cfg->name);
1301         hfri.hfinfo.blurb = g_strdup_printf("Duration in seconds from start to stop of this %s",cfg->name);
1302
1303         g_array_append_val(matecfg->hfrs,hfri);
1304
1305         hfri.p_id = &(cfg->hfid_last_time);
1306         hfri.hfinfo.name = g_strdup_printf("%s duration",cfg->name);
1307         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Duration",cfg->name);
1308         hfri.hfinfo.blurb = g_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name);
1309
1310         g_array_append_val(matecfg->hfrs,hfri);
1311
1312         hfri.p_id = &(cfg->hfid_gop_num_pdus);
1313         hfri.hfinfo.name = g_strdup_printf("%s number of PDUs",cfg->name);
1314         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.NumOfPdus",cfg->name);
1315         hfri.hfinfo.blurb = g_strdup_printf("Number of PDUs assigned to this %s",cfg->name);
1316         hfri.hfinfo.type = FT_UINT32;
1317
1318         g_array_append_val(matecfg->hfrs,hfri);
1319
1320         hfri.p_id = &(cfg->hfid_gop_pdu);
1321         hfri.hfinfo.name = g_strdup_printf("A PDU of %s",cfg->name);
1322         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Pdu",cfg->name);
1323         hfri.hfinfo.blurb = g_strdup_printf("A PDU assigned to this %s",cfg->name);
1324
1325         if (cfg->show_pdu_tree == matecfg->frame_tree) {
1326                 hfri.hfinfo.type = FT_FRAMENUM;
1327                 g_array_append_val(matecfg->hfrs,hfri);
1328         } else  if (cfg->show_pdu_tree == matecfg->pdu_tree) {
1329                 hfri.hfinfo.type = FT_UINT32;
1330                 g_array_append_val(matecfg->hfrs,hfri);
1331         } else {
1332                 cfg->show_pdu_tree = matecfg->no_tree;
1333         }
1334
1335         while(( avp = get_next_avp(cfg->key,&cookie) )) {
1336                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1337                         new_attr_hfri(cfg,avp->n);
1338                 }
1339         }
1340
1341         if(cfg->start) {
1342                 cookie = NULL;
1343                 while(( avp = get_next_avp(cfg->start,&cookie) )) {
1344                         if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1345                                 new_attr_hfri(cfg,avp->n);
1346                         }
1347                 }
1348         }
1349         
1350         if (cfg->stop) {
1351                 cookie = NULL;
1352                 while(( avp = get_next_avp(cfg->stop,&cookie) )) {
1353                         if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1354                                 new_attr_hfri(cfg,avp->n);
1355                         }
1356                 }
1357         }
1358         
1359         cookie = NULL;
1360         while(( avp = get_next_avp(cfg->extra,&cookie) )) {
1361                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1362                         new_attr_hfri(cfg,avp->n);
1363                 }
1364         }
1365
1366         analyze_transform_hfrs(cfg);
1367
1368         ett = &cfg->ett;
1369         g_array_append_val(matecfg->ett,ett);
1370
1371         ett = &cfg->ett_attr;
1372         g_array_append_val(matecfg->ett,ett);
1373
1374         ett = &cfg->ett_times;
1375         g_array_append_val(matecfg->ett,ett);
1376
1377         ett = &cfg->ett_children;
1378         g_array_append_val(matecfg->ett,ett);
1379
1380 }
1381
1382
1383 static void analyze_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
1384         mate_cfg_gop* cfg = v;
1385         void* avp_cookie;
1386         void* avpl_cookie;
1387         AVP* avp;
1388         AVPL* avpl;
1389         AVPL* key_avps;
1390         hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
1391         gint* ett;
1392
1393         hfri.p_id = &(cfg->hfid);
1394         hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
1395         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
1396         hfri.hfinfo.blurb = g_strdup_printf("%s Id",cfg->name);
1397         hfri.hfinfo.type = FT_UINT32;
1398         hfri.hfinfo.display = BASE_DEC;
1399
1400         g_array_append_val(matecfg->hfrs,hfri);
1401         
1402         hfri.p_id = &(cfg->hfid_gog_num_of_gops);
1403         hfri.hfinfo.name = "number of GOPs";
1404         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.NumOfGops",cfg->name);
1405         hfri.hfinfo.type = FT_UINT32;
1406         hfri.hfinfo.display = BASE_DEC;
1407         hfri.hfinfo.blurb = g_strdup_printf("Number of GOPs assigned to this %s",cfg->name);
1408         
1409         g_array_append_val(matecfg->hfrs,hfri);
1410         
1411         hfri.p_id = &(cfg->hfid_gog_gopstart);
1412         hfri.hfinfo.name = "GopStart frame";
1413         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.GopStart",cfg->name);
1414         hfri.hfinfo.type = FT_FRAMENUM;
1415         hfri.hfinfo.display = BASE_DEC;
1416         hfri.hfinfo.blurb = g_strdup("The start frame of a GOP");
1417         
1418         g_array_append_val(matecfg->hfrs,hfri);
1419         
1420         hfri.p_id = &(cfg->hfid_start_time);
1421         hfri.hfinfo.name = g_strdup_printf("%s start time",cfg->name);
1422         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.StartTime",cfg->name);
1423         hfri.hfinfo.type = FT_FLOAT;
1424         hfri.hfinfo.blurb = g_strdup_printf("Seconds passed since the begining of caputre to the start of this %s",cfg->name);
1425         
1426         g_array_append_val(matecfg->hfrs,hfri);
1427                 
1428         hfri.p_id = &(cfg->hfid_last_time);
1429         hfri.hfinfo.name = g_strdup_printf("%s duration",cfg->name);
1430         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Duration",cfg->name);
1431         hfri.hfinfo.blurb = g_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name);
1432         
1433         g_array_append_val(matecfg->hfrs,hfri);
1434         
1435         /* this might become mate.gogname.gopname */
1436         hfri.p_id = &(cfg->hfid_gog_gop);
1437         hfri.hfinfo.name = "a GOP";
1438         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Gop",cfg->name);
1439         hfri.hfinfo.type = FT_STRING;
1440         hfri.hfinfo.display = BASE_DEC;
1441         hfri.hfinfo.blurb = g_strdup_printf("a GOPs assigned to this %s",cfg->name);
1442
1443         g_array_append_val(matecfg->hfrs,hfri);
1444
1445         key_avps = new_avpl("");
1446         
1447         avpl_cookie = NULL;
1448         while (( avpl = get_next_avpl(cfg->keys,&avpl_cookie) )) {
1449                 avp_cookie = NULL;
1450                 while (( avp = get_next_avp(avpl,&avp_cookie) )) {
1451                         if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1452                                 new_attr_hfri(cfg,avp->n);
1453                                 insert_avp(key_avps,avp);
1454                         }
1455                 }
1456         }
1457
1458         avp_cookie = NULL;
1459         while (( avp = get_next_avp(cfg->extra,&avp_cookie) )) {
1460                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1461                         new_attr_hfri(cfg,avp->n);
1462                 }
1463         }
1464         
1465         merge_avpl(cfg->extra,key_avps,TRUE);
1466         
1467         analyze_transform_hfrs(cfg);
1468
1469         ett = &cfg->ett;
1470         g_array_append_val(matecfg->ett,ett);
1471
1472         ett = &cfg->ett_attr;
1473         g_array_append_val(matecfg->ett,ett);
1474
1475         ett = &cfg->ett_children;
1476         g_array_append_val(matecfg->ett,ett);
1477
1478         ett = &cfg->ett_times;
1479         g_array_append_val(matecfg->ett,ett);
1480         
1481         ett = &cfg->ett_gog_gop;        
1482         g_array_append_val(matecfg->ett,ett);
1483         
1484 }
1485
1486 static void analyze_config(void) {
1487         guint i;
1488
1489         for (i=0; i<matecfg->pducfglist->len; i++) {
1490                 analyze_pdu_config((mate_cfg_pdu*) g_ptr_array_index(matecfg->pducfglist,i));
1491         }
1492
1493         g_hash_table_foreach(matecfg->gopcfgs,analyze_gop_config,matecfg);
1494         g_hash_table_foreach(matecfg->gogcfgs,analyze_gog_config,matecfg);
1495
1496 }
1497
1498 static void new_action(guint8* name, config_action* action) {
1499         g_hash_table_insert(actions,name,action);
1500
1501 }
1502
1503 static void init_actions(void) {
1504         AVP* avp;
1505
1506         all_keywords = new_avpl("all_keywords");
1507
1508         insert_avp(all_keywords,new_avp(KEYWORD_ACTION,"",'='));
1509         insert_avp(all_keywords,new_avp(KEYWORD_SETTINGS,"",'='));
1510         insert_avp(all_keywords,new_avp(KEYWORD_INCLUDE,"",'='));
1511         insert_avp(all_keywords,new_avp(KEYWORD_TRANSFORM,"",'='));
1512         insert_avp(all_keywords,new_avp(KEYWORD_PDU,"",'='));
1513         insert_avp(all_keywords,new_avp(KEYWORD_PDUCRITERIA,"",'='));
1514         insert_avp(all_keywords,new_avp(KEYWORD_PDUEXTRA,"",'='));
1515         insert_avp(all_keywords,new_avp(KEYWORD_PDUTRANSFORM,"",'='));
1516         insert_avp(all_keywords,new_avp(KEYWORD_GOP,"",'='));
1517         insert_avp(all_keywords,new_avp(KEYWORD_GOPSTART,"",'='));
1518         insert_avp(all_keywords,new_avp(KEYWORD_GOPSTOP,"",'='));
1519         insert_avp(all_keywords,new_avp(KEYWORD_GOPEXTRA,"",'='));
1520         insert_avp(all_keywords,new_avp(KEYWORD_GOPTRANSFORM,"",'='));
1521         insert_avp(all_keywords,new_avp(KEYWORD_GOGDEF,"",'='));
1522         insert_avp(all_keywords,new_avp(KEYWORD_GOGKEY,"",'='));
1523         insert_avp(all_keywords,new_avp(KEYWORD_GOGEXTRA,"",'='));
1524         insert_avp(all_keywords,new_avp(KEYWORD_GOGTRANSFORM,"",'='));
1525         insert_avp(all_keywords,new_avp(KEYWORD_NAME,"",'='));
1526         insert_avp(all_keywords,new_avp(KEYWORD_ON,"",'='));
1527         insert_avp(all_keywords,new_avp(KEYWORD_FOR,"",'='));
1528         insert_avp(all_keywords,new_avp(KEYWORD_FROM,"",'='));
1529         insert_avp(all_keywords,new_avp(KEYWORD_TO,"",'='));
1530         insert_avp(all_keywords,new_avp(KEYWORD_MATCH,"",'='));
1531         insert_avp(all_keywords,new_avp(KEYWORD_MODE,"",'='));
1532         insert_avp(all_keywords,new_avp(KEYWORD_FILENAME,"",'='));
1533         insert_avp(all_keywords,new_avp(KEYWORD_PROTO,"",'='));
1534         insert_avp(all_keywords,new_avp(KEYWORD_METHOD,"",'='));
1535         insert_avp(all_keywords,new_avp(KEYWORD_TRANSPORT,"",'='));
1536         insert_avp(all_keywords,new_avp(KEYWORD_METHOD,"",'='));
1537         insert_avp(all_keywords,new_avp(KEYWORD_STRICT,"",'='));
1538         insert_avp(all_keywords,new_avp(KEYWORD_LOOSE,"",'='));
1539         insert_avp(all_keywords,new_avp(KEYWORD_EVERY,"",'='));
1540         insert_avp(all_keywords,new_avp(KEYWORD_REPLACE,"",'='));
1541         insert_avp(all_keywords,new_avp(KEYWORD_INSERT,"",'='));
1542         insert_avp(all_keywords,new_avp(KEYWORD_MAP,"",'='));
1543         insert_avp(all_keywords,new_avp(KEYWORD_GOGEXPIRE,"",'='));
1544         insert_avp(all_keywords,new_avp(KEYWORD_DISCARDPDU,"",'='));
1545         insert_avp(all_keywords,new_avp(KEYWORD_LIBPATH,"",'='));
1546         insert_avp(all_keywords,new_avp(KEYWORD_SHOWPDUTREE,"",'='));
1547         insert_avp(all_keywords,new_avp(KEYWORD_SHOWGOPTIMES,"",'='));
1548         insert_avp(all_keywords,new_avp(KEYWORD_STOP,"",'='));
1549         insert_avp(all_keywords,new_avp(KEYWORD_DROPPDU,"",'='));
1550         insert_avp(all_keywords,new_avp(KEYWORD_DROPGOP,"",'='));
1551         insert_avp(all_keywords,new_avp(KEYWORD_LIB,"",'='));
1552
1553         insert_avp(all_keywords,new_avp(KEYWORD_DBG_GENERAL,"",'='));
1554         insert_avp(all_keywords,new_avp(KEYWORD_DBG_CFG,"",'='));
1555         insert_avp(all_keywords,new_avp(KEYWORD_DBG_PDU,"",'='));
1556         insert_avp(all_keywords,new_avp(KEYWORD_DBG_GOP,"",'='));
1557         insert_avp(all_keywords,new_avp(KEYWORD_DBG_GOG,"",'='));
1558
1559 #ifdef _AVP_DEBUGGING
1560         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPLIB,"",'='));
1561         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVP,"",'='));
1562         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVP_OP,"",'='));
1563         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPL,"",'='));
1564         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPL_OP,"",'='));
1565 #endif
1566
1567         avp = new_avp(KEYWORD_ACCEPT,"",'=');
1568         matecfg->accept = avp->n;
1569         insert_avp(all_keywords,avp);
1570
1571         avp = new_avp(KEYWORD_REJECT,"",'=');
1572         matecfg->reject = avp->n;
1573         insert_avp(all_keywords,avp);
1574
1575         avp = new_avp(KEYWORD_NOTREE,"",'=');
1576         matecfg->no_tree = avp->n;
1577         insert_avp(all_keywords,avp);
1578
1579         avp = new_avp(KEYWORD_FRAMETREE,"",'=');
1580         matecfg->frame_tree = avp->n;
1581         insert_avp(all_keywords,avp);
1582
1583         avp = new_avp(KEYWORD_PDUTREE,"",'=');
1584         matecfg->pdu_tree = avp->n;
1585         insert_avp(all_keywords,avp);
1586         
1587         if (actions) {
1588                 g_hash_table_destroy(actions);
1589         }
1590
1591         actions = g_hash_table_new(g_str_hash,g_str_equal);
1592
1593         new_action(KEYWORD_SETTINGS,config_settings);
1594         new_action(KEYWORD_PDU,config_pdu);
1595         new_action(KEYWORD_PDUEXTRA,config_pduextra);
1596         new_action(KEYWORD_PDUCRITERIA,config_pducriteria);
1597         new_action(KEYWORD_GOP,config_gop);
1598         new_action(KEYWORD_GOGDEF,config_gog);
1599         new_action(KEYWORD_GOGKEY,config_gogkey);
1600         new_action(KEYWORD_GOPSTART,config_start);
1601         new_action(KEYWORD_GOPSTOP,config_stop);
1602         new_action(KEYWORD_GOPEXTRA,config_gopextra);
1603         new_action(KEYWORD_GOGEXTRA,config_gogextra);
1604         new_action(KEYWORD_INCLUDE,config_include);
1605         new_action(KEYWORD_TRANSFORM,config_transform);
1606         new_action(KEYWORD_PDUTRANSFORM,config_pdu_transform);
1607         new_action(KEYWORD_GOPTRANSFORM,config_gop_transform);
1608         new_action(KEYWORD_GOGTRANSFORM,config_gog_transform);
1609
1610 }
1611
1612 extern mate_config* mate_cfg() {
1613         return matecfg;
1614 }
1615
1616 extern mate_config* mate_make_config(guint8* filename, int mate_hfid) {
1617         gint* ett;
1618
1619         avp_init();
1620
1621         matecfg = g_malloc(sizeof(mate_config));
1622
1623         matecfg->gog_expiration = DEFAULT_GOG_EXPIRATION;
1624         matecfg->discard_pdu_attributes = FALSE;
1625         matecfg->drop_pdu = FALSE;
1626         matecfg->drop_gop = FALSE;
1627         matecfg->show_times = TRUE;
1628         matecfg->last_to_be_created = FALSE;
1629         matecfg->match_mode = AVPL_STRICT;
1630         matecfg->replace_mode = AVPL_INSERT;
1631         matecfg->mate_lib_path = g_strdup_printf("%s%c%s%c",get_datafile_dir(),DIR_SEP,DEFAULT_MATE_LIB_PATH,DIR_SEP);
1632         matecfg->mate_config_file = g_strdup(filename);
1633         matecfg->mate_attrs_filter = g_string_new("");
1634         matecfg->mate_protos_filter = g_string_new("");
1635         matecfg->dbg_facility = NULL;
1636         matecfg->dbg_lvl = 0;
1637         matecfg->dbg_cfg_lvl = 0;
1638         matecfg->dbg_pdu_lvl = 0;
1639         matecfg->dbg_gop_lvl = 0;
1640         matecfg->dbg_gog_lvl = 0;
1641         matecfg->pducfglist = g_ptr_array_new();
1642         matecfg->pducfgs = g_hash_table_new(g_str_hash,g_str_equal);
1643         matecfg->gopcfgs = g_hash_table_new(g_str_hash,g_str_equal);
1644         matecfg->gogcfgs = g_hash_table_new(g_str_hash,g_str_equal);
1645         matecfg->transfs = g_hash_table_new(g_str_hash,g_str_equal);
1646         matecfg->gops_by_pduname = g_hash_table_new(g_str_hash,g_str_equal);
1647         matecfg->gogs_by_gopname = g_hash_table_new(g_str_hash,g_str_equal);
1648
1649         matecfg->hfrs = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
1650         matecfg->ett = g_array_new(FALSE,TRUE,sizeof(gint*));
1651         matecfg->ett_root = -1;
1652         matecfg->hfid_mate = mate_hfid;
1653         
1654         ett = &matecfg->ett_root;
1655         g_array_append_val(matecfg->ett,ett);
1656
1657         dbg = &matecfg->dbg_lvl;
1658
1659         init_actions();
1660
1661         matecfg->show_pdu_tree = matecfg->frame_tree;
1662
1663         config_error = g_string_new("");
1664         
1665         if ( mate_load_config(filename) ) {
1666                 analyze_config();
1667                 dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: OK");
1668                 if (dbg_cfg_lvl > 0) print_config();
1669         } else {
1670                 report_failure("%s",config_error->str);
1671                 g_string_free(config_error,TRUE);
1672                 if (matecfg) destroy_mate_config(matecfg,FALSE);
1673                 matecfg = NULL;
1674                 return NULL;
1675         }
1676
1677         if (matecfg->mate_attrs_filter->len > 1) {
1678                 g_string_erase(matecfg->mate_attrs_filter,0,2);
1679                 g_string_erase(matecfg->mate_protos_filter,0,2);
1680         } else {
1681                 destroy_mate_config(matecfg,FALSE);
1682                 matecfg = NULL;
1683                 return NULL;
1684         }
1685
1686         matecfg->tap_filter = g_strdup_printf("(%s) && (%s)",matecfg->mate_protos_filter->str,matecfg->mate_attrs_filter->str);
1687
1688         return matecfg;
1689 }
1690