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