two fixes in config loading:
[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->pducfgs,on) == NULL ) {
738                 report_error("MATE: GopDef: Pdu '%s' does not exist in: %s",on,avpl->name);
739                 return FALSE;           
740         }
741
742         if (g_hash_table_lookup(matecfg->gops_by_pduname,on) ) {
743                 report_error("MATE: GopDef: Gop for Pdu '%s' exists already in: %s",on,avpl->name);
744                 return FALSE;
745         } else {
746                 g_hash_table_insert(matecfg->gops_by_pduname,on,cfg);
747         }
748
749         cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,matecfg->drop_gop);
750         cfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE, matecfg->show_pdu_tree);
751         cfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,matecfg->show_times);
752         cfg->expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,matecfg->gop_expiration);
753         cfg->idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,matecfg->gop_idle_timeout);
754         cfg->lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,matecfg->gop_lifetime);
755         
756         cfg->key = avpl;
757
758         return TRUE;
759 }
760
761 static gboolean config_start(AVPL* avpl) {
762         guint8* name;
763         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
764
765         if (! name ) {
766                 report_error("MATE: GopStart: no For in: %s",avpl->name);
767                 return FALSE;
768         }
769         
770         if (!cfg) {
771                 report_error("MATE: GopStart: Gop '%s' doesn't exist in: %s",name,avpl->name);
772                 return FALSE;
773         }
774
775         if (cfg->start) {
776                 /* FEATURE: more start conditions */
777                 report_error("MATE: GopStart: GopStart for '%s' exists already in: %s",name,avpl->name);
778                 return FALSE;
779         }
780
781         cfg->start = avpl;
782
783         return TRUE;
784 }
785
786 static gboolean config_stop(AVPL* avpl) {
787         guint8* name;
788         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
789         
790         if (! name ) {
791                 report_error("MATE: GopStop: no For in: %s",avpl->name);
792                 return FALSE;
793         }
794         
795         if (!cfg) {
796                 report_error("MATE: GopStop: Gop '%s' doesn't exist in: %s",name,avpl->name);
797                 return FALSE;
798         }
799
800         if (cfg->stop) {
801                 report_error("MATE: GopStop: GopStop alredy exists for '%s' in: %s",name,avpl->name);
802                 return FALSE;
803         }
804
805         cfg->stop = avpl;
806
807         return TRUE;
808 }
809
810 static gboolean config_gopextra(AVPL* avpl) {
811         guint8* name;
812         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gopcfgs,&name);;
813
814         if (! name ) {
815                 report_error("MATE: GopExtra: no For in: %s",avpl->name);
816                 return FALSE;
817         }
818         
819         if (!cfg) {
820                 report_error("MATE: GopExtra: Gop '%s' does not exist in: %s",name,avpl->name);
821                 return FALSE;
822         }
823
824         cfg->drop_gop = extract_named_bool(avpl, KEYWORD_DROPGOP,cfg->drop_gop);
825         cfg->show_pdu_tree = extract_named_str(avpl, KEYWORD_SHOWPDUTREE, cfg->show_pdu_tree);
826         cfg->show_times = extract_named_bool(avpl, KEYWORD_SHOWGOPTIMES,cfg->show_times);
827         cfg->expiration = extract_named_float(avpl, KEYWORD_GOPEXPIRATION,cfg->expiration);
828         cfg->idle_timeout = extract_named_float(avpl, KEYWORD_GOPIDLETIMEOUT,cfg->idle_timeout);
829         cfg->lifetime = extract_named_float(avpl, KEYWORD_GOPLIFETIME,cfg->lifetime);
830         
831         merge_avpl(cfg->extra,avpl,TRUE);
832
833         return TRUE;
834 }
835
836 static gboolean config_gog(AVPL* avpl) {
837         guint8* name = extract_named_str(avpl, KEYWORD_NAME,NULL);
838         mate_cfg_gog* cfg = NULL;
839
840         if (! name ) {
841                 report_error("MATE: GogDef: no Name in: %s",avpl->name);
842                 return FALSE;
843         }
844         
845         if ( g_hash_table_lookup(matecfg->gogcfgs,name) ) {
846                 report_error("MATE: GogDef: Gog '%s' exists already in: %s",name,avpl->name);
847                 return FALSE;
848         }
849
850         cfg = new_gogcfg(name);
851
852         cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,matecfg->gog_expiration);
853         cfg->gop_as_subtree = extract_named_bool(avpl, KEYWORD_GOPTREE,matecfg->gop_as_subtree);
854         
855         return TRUE;
856 }
857
858 static gboolean config_gogkey(AVPL* avpl) {
859         guint8* name;
860         mate_cfg_gog* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gogcfgs,&name);
861         AVPL* reverse_avpl;
862         LoAL* gogkeys;
863         guint8* on = extract_named_str(avpl,KEYWORD_ON,NULL);
864
865         if ( ! name || ! cfg ) {
866                 if ( ! name )
867                         report_error("MATE: GogKey: no For in %s",avpl->name);
868                 else
869                         report_error("MATE: GogKey: no such Gop '%s' in %s",name,avpl->name);
870
871                 return FALSE;
872         }
873
874         if (! on ) {
875                 report_error("MATE: GogKey: no On in %s",avpl->name);
876                 return FALSE;
877         }
878
879         rename_avpl(avpl,name);
880
881         gogkeys = (LoAL*) g_hash_table_lookup(matecfg->gogs_by_gopname,on);
882
883         if (! gogkeys) {
884                 gogkeys = new_loal("straight");
885                 g_hash_table_insert(matecfg->gogs_by_gopname,g_strdup(on),gogkeys);
886         }
887
888         loal_append(gogkeys,avpl);
889
890         reverse_avpl = new_avpl_from_avpl(on,avpl,TRUE);
891
892         loal_append(cfg->keys,reverse_avpl);
893
894         return TRUE;
895 }
896
897 static gboolean config_gogextra(AVPL* avpl) {
898         guint8* name;
899         mate_cfg_gop* cfg = lookup_using_index_avp(avpl, KEYWORD_FOR,matecfg->gogcfgs,&name);
900
901         if ( ! name || ! cfg ) {
902                 if ( ! name )
903                         report_error("MATE: GogExtra: no Name in %s",avpl->name);
904                 else
905                         report_error("MATE: GogExtra: no such Gop '%s' in %s",name,avpl->name);
906
907                 return FALSE;
908         }
909
910         cfg->expiration = extract_named_float(avpl, KEYWORD_GOGEXPIRE,cfg->expiration);
911         cfg->gop_as_subtree = extract_named_bool(avpl, KEYWORD_GOPTREE,cfg->gop_as_subtree);
912
913         merge_avpl(cfg->extra,avpl,TRUE);
914
915         return TRUE;
916 }
917
918 #define true_false_str(v) ((v) ? "TRUE" : "FALSE")
919
920 static void print_xxx_transforms(mate_cfg_item* cfg) {
921         guint8* tr_name;
922         guint8* cfg_name;
923         guint i;
924
925         switch (cfg->type) {
926                 case MATE_PDU_TYPE:
927                         cfg_name = "PduTransform";
928                         break;
929                 case MATE_GOP_TYPE:
930                         cfg_name = "GopTransform";
931                         break;
932                 case MATE_GOG_TYPE:
933                         cfg_name = "GogTransform";
934                         break;
935                 default:
936                         cfg_name = "UnknownTransform";
937                         break;
938         }
939
940         for (i=0; i < cfg->transforms->len; i++) {
941                 tr_name = ((AVPL_Transf*) g_ptr_array_index(cfg->transforms,i))->name;
942                 dbg_print (dbg_cfg,0,dbg_facility,"Action=%s; For=%s; Name=%s;",cfg_name,cfg->name,tr_name);
943         }
944
945 }
946
947 static void print_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
948         mate_cfg_gop* cfg = (mate_cfg_gop*) v;
949         guint8* avplstr = NULL;
950         void* cookie = NULL;
951         AVPL* avpl;
952
953         dbg_print (dbg_cfg,0,dbg_facility,"Action=GogDef; Name=%s; Expiration=%f;",cfg->name,cfg->expiration);
954
955         if (cfg->keys) {
956                 while (( avpl = get_next_avpl(cfg->keys,&cookie) )) {
957                         avplstr = avpl_to_str(avpl);
958                         dbg_print (dbg_cfg,0,dbg_facility,"Action=GogKey; For=%s; On=%s; %s",cfg->name,avpl->name,avplstr);
959                         g_free(avplstr);
960                 }
961         }
962
963         if (cfg->extra) {
964                 avplstr = avpl_to_str(cfg->extra);
965                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GogExtra; For=%s; %s",cfg->name,avplstr);
966                 g_free(avplstr);
967         }
968
969         print_xxx_transforms(cfg);
970
971 }
972
973
974
975 static void print_gop_config(gpointer k _U_ , gpointer v, gpointer p _U_) {
976         mate_cfg_gop* cfg = (mate_cfg_gop*) v;
977         guint8* avplstr = NULL;
978         guint8* show_pdu_tree;
979         GString* gopdef;
980
981         gopdef = g_string_new("Action=GopDef; ");
982
983         show_pdu_tree = cfg->show_pdu_tree ? "TRUE" : "FALSE";
984         g_string_sprintfa(gopdef,"Name=%s; ShowPduTree=%s; ShowGopTimes=%s; "
985                                           "GopExpiration=%f; GopIdleTimeout=%f GopLifetime=%f;",
986                                           cfg->name,show_pdu_tree,true_false_str(cfg->show_times),
987                                           cfg->expiration,cfg->idle_timeout,cfg->lifetime);
988
989         if (cfg->key) {
990                 avplstr = avpl_to_str(cfg->key);
991                 g_string_sprintfa(gopdef," %s",avplstr);
992                 g_free(avplstr);
993         }
994
995         dbg_print (dbg_cfg,0,dbg_facility,"%s",gopdef->str);
996
997
998         if (cfg->start) {
999                 avplstr = avpl_to_str(cfg->start);
1000                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStart; For=%s; %s",cfg->name,avplstr);
1001                 g_free(avplstr);
1002         }
1003
1004         if (cfg->stop) {
1005                 avplstr = avpl_to_str(cfg->stop);
1006                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GopStop; For=%s; %s",cfg->name,avplstr);
1007                 g_free(avplstr);
1008         }
1009
1010         if (cfg->extra) {
1011                 avplstr = avpl_to_str(cfg->extra);
1012                 dbg_print (dbg_cfg,0,dbg_facility,"Action=GopExtra; For=%s;  %s",cfg->name,avplstr);
1013                 g_free(avplstr);
1014         }
1015
1016         print_xxx_transforms(cfg);
1017
1018         g_string_free(gopdef,TRUE);
1019
1020 }
1021
1022 static guint8* my_protoname(int proto_id) {
1023         if (proto_id) {
1024                 return proto_registrar_get_abbrev(proto_id);
1025         } else {
1026                 return "*";
1027         }
1028 }
1029
1030 static void print_hfid_hash(gpointer k, gpointer v, gpointer p _U_) {
1031         g_string_sprintfa((GString*)p," %s=%s;",(guint8*)v,my_protoname(*(int*)k));
1032 }
1033
1034
1035 static void print_transforms(gpointer k, gpointer v, gpointer p _U_) {
1036         AVPL_Transf* t = NULL;
1037         guint8* match;
1038         guint8* mode;
1039         guint8* match_s;
1040         guint8* replace_s;
1041
1042         for (t = v; t; t = t->next) {
1043                 match_s =  avpl_to_str(t->match);
1044                 replace_s = avpl_to_dotstr(t->replace);
1045
1046                 switch (t->match_mode) {
1047                         case AVPL_STRICT:
1048                                 match = "Strict";
1049                                 break;
1050                         case AVPL_LOOSE:
1051                                 match = "Loose";
1052                                 break;
1053                         case AVPL_EVERY:
1054                                 match = "Every";
1055                                 break;
1056                         default:
1057                                 match = "None";
1058                                 break;
1059                 }
1060
1061                 switch (t->replace_mode) {
1062                         case AVPL_INSERT:
1063                                 mode = "Insert";
1064                                 break;
1065                         case AVPL_REPLACE:
1066                                 mode = "Replace";
1067                                 break;
1068                         default:
1069                                 mode = "None";
1070                                 break;
1071                 }
1072
1073                 dbg_print (dbg,0,dbg_facility,"\tAction=Transform; Name=%s; Match=%s; Mode=%s; %s %s",(guint8*) k,match,mode,match_s,replace_s);
1074
1075                 g_free(match_s);
1076                 g_free(replace_s);
1077         }
1078 }
1079
1080 static void print_pdu_config(mate_cfg_pdu* cfg) {
1081         guint i;
1082         int hfid;
1083         guint8* discard;
1084         guint8* stop;
1085         guint8* criterium_match = NULL;
1086         guint8* criterium;
1087         GString* s = g_string_new("Action=PduDef; ");
1088
1089         discard = cfg->discard_pdu_attributes ? "TRUE": "FALSE";
1090         stop = cfg->last_to_be_created ? "TRUE" : "FALSE";
1091
1092         g_string_sprintfa(s, "Name=%s; Proto=%s; DiscartAttribs=%s; Stop=%s;  Transport=",
1093                                           cfg->name,my_protoname(cfg->hfid_proto),discard,stop);
1094
1095         for (i = 0; i < cfg->hfid_ranges->len; i++) {
1096                 hfid = *((int*) g_ptr_array_index(cfg->hfid_ranges,i));
1097                 g_string_sprintfa(s,"%s/",my_protoname(hfid));
1098         }
1099
1100         *(s->str + s->len - 1) = ';';
1101
1102         g_hash_table_foreach(cfg->hfids_attr,print_hfid_hash,s);
1103
1104         dbg_print(dbg_cfg,0,dbg_facility,"%s",s->str);
1105
1106         if (cfg->criterium) {
1107                 switch(cfg->criterium_match_mode) {
1108                         case AVPL_NO_MATCH:
1109                                 criterium_match = "None";
1110                                 break;
1111                         case AVPL_STRICT:
1112                                 criterium_match = "Strict";
1113                                 break;
1114                         case AVPL_LOOSE:
1115                                 criterium_match = "Loose";
1116                                 break;
1117                         case AVPL_EVERY:
1118                                 criterium_match = "Every";
1119                                 break;
1120                 }
1121
1122                 criterium = avpl_to_str(cfg->criterium);
1123
1124                 dbg_print(dbg_cfg,0,dbg_facility,
1125                                   "Action=PduCriteria; For=%s; Match=%s; Mode=%s;  %s",
1126                                   cfg->name,criterium_match,cfg->criterium->name,criterium);
1127
1128                 g_free(criterium);
1129         }
1130
1131         print_xxx_transforms(cfg);
1132
1133         g_string_free(s,TRUE);
1134 }
1135
1136
1137
1138 static void print_gogs_by_gopname(gpointer k, gpointer v, gpointer p _U_) {
1139         void* cookie = NULL;
1140         guint8* str = NULL;
1141         AVPL* avpl;
1142
1143         while(( avpl = get_next_avpl((LoAL*)v,&cookie) )) {
1144                 str = avpl_to_str(avpl);
1145                 dbg_print(dbg_cfg,0,dbg_facility,"Gop=%s; Gog=%s; --> %s",(guint8*)k,avpl->name,str);
1146                 g_free(str);
1147         }
1148
1149 }
1150
1151 static void print_gops_by_pduname(gpointer k, gpointer v, gpointer p _U_) {
1152         dbg_print(dbg_cfg,0,dbg_facility,
1153                           "PduName=%s; GopName=%s;", (guint8*)k,((mate_cfg_gop*)v)->name);
1154 }
1155
1156 static void print_config(void) {
1157         guint i;
1158
1159         /* FIXME: print the settings */
1160
1161         dbg_print(dbg_cfg,0,dbg_facility,"###########################"
1162                           " CURRENT CONFIGURATION " "###########################");
1163
1164         g_hash_table_foreach(matecfg->transfs,print_transforms,NULL);
1165
1166         for (i=0; i<matecfg->pducfglist->len; i++) {
1167                 print_pdu_config((mate_cfg_pdu*) g_ptr_array_index(matecfg->pducfglist,i));
1168         }
1169
1170         g_hash_table_foreach(matecfg->gopcfgs,print_gop_config,NULL);
1171         g_hash_table_foreach(matecfg->gogcfgs,print_gog_config,NULL);
1172
1173         dbg_print(dbg_cfg,0,dbg_facility,"###########################"
1174                           " END OF CURRENT CONFIGURATION " "###########################");
1175
1176         if (*dbg_cfg > 1) {
1177                 dbg_print(dbg_cfg,0,dbg_facility,"******* Config Hashes");
1178                 dbg_print(dbg_cfg,0,dbg_facility,"*** Gops by PduName");
1179                 g_hash_table_foreach(matecfg->gops_by_pduname,print_gops_by_pduname,NULL);
1180                 dbg_print(dbg_cfg,0,dbg_facility,"*** GogKeys by GopName");
1181                 g_hash_table_foreach(matecfg->gogs_by_gopname,print_gogs_by_gopname,NULL);
1182         }
1183 }
1184
1185
1186 static void new_attr_hfri(mate_cfg_item* cfg, guint8* name) {
1187         int* p_id = g_malloc(sizeof(int));
1188
1189         hf_register_info hfri;
1190
1191         memset(&hfri, 0, sizeof hfri);
1192         hfri.p_id = p_id;
1193         hfri.hfinfo.name = g_strdup_printf("%s",name);
1194         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.%s",cfg->name,name);
1195         hfri.hfinfo.type = FT_STRING;
1196         hfri.hfinfo.display = BASE_NONE;
1197         hfri.hfinfo.strings = NULL;
1198         hfri.hfinfo.bitmask = 0;
1199         hfri.hfinfo.blurb = g_strdup_printf("%s attribute of %s",name,cfg->name);
1200
1201         *p_id = -1;
1202         g_hash_table_insert(cfg->my_hfids,name,p_id);
1203         g_array_append_val(matecfg->hfrs,hfri);
1204
1205 }
1206
1207 static void analyze_pdu_hfids(gpointer k _U_, gpointer v, gpointer p) {
1208         new_attr_hfri((mate_cfg_pdu*) p,(guint8*) v);
1209 }
1210
1211 static void analyze_transform_hfrs(mate_cfg_item* cfg) {
1212         guint i;
1213         void* cookie = NULL;
1214         AVPL_Transf* t;
1215         AVP* avp;
1216
1217         for (i=0; i < cfg->transforms->len;i++) {
1218                 for (t = g_ptr_array_index(cfg->transforms,i); t; t=t->next ) {
1219                         cookie = NULL;
1220                         while(( avp = get_next_avp(t->replace,&cookie) )) {
1221                                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1222                                         new_attr_hfri(cfg,avp->n);
1223                                 }
1224                         }
1225                 }
1226         }
1227 }
1228
1229 static void analyze_pdu_config(mate_cfg_pdu* cfg) {
1230         hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
1231         gint* ett;
1232
1233         hfri.p_id = &(cfg->hfid);
1234         hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
1235         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
1236         hfri.hfinfo.blurb = g_strdup_printf("%s id",cfg->name);
1237         hfri.hfinfo.type = FT_UINT32;
1238         hfri.hfinfo.display = BASE_DEC;
1239
1240         g_array_append_val(matecfg->hfrs,hfri);
1241         
1242         hfri.p_id = &(cfg->hfid_pdu_rel_time);
1243         hfri.hfinfo.name = g_strdup_printf("%s time",cfg->name);
1244         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.RelativeTime",cfg->name);
1245         hfri.hfinfo.type = FT_FLOAT;
1246         hfri.hfinfo.display = BASE_DEC;
1247         hfri.hfinfo.blurb = "Seconds passed since the start of capture";
1248         
1249         g_array_append_val(matecfg->hfrs,hfri);
1250         
1251         hfri.p_id = &(cfg->hfid_pdu_time_in_gop);
1252         hfri.hfinfo.name = g_strdup_printf("%s time since begining of Gop",cfg->name);
1253         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.TimeInGop",cfg->name);
1254         hfri.hfinfo.type = FT_FLOAT;
1255         hfri.hfinfo.display = BASE_DEC;
1256         hfri.hfinfo.blurb = "Seconds passed since the start of the GOP";
1257         
1258         g_array_append_val(matecfg->hfrs,hfri);
1259         
1260         g_hash_table_foreach(cfg->hfids_attr,analyze_pdu_hfids,cfg);
1261
1262         ett = &cfg->ett;
1263         g_array_append_val(matecfg->ett,ett);
1264
1265         ett = &cfg->ett_attr;
1266         g_array_append_val(matecfg->ett,ett);
1267
1268         analyze_transform_hfrs(cfg);
1269 }
1270
1271 static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p _U_) {
1272         mate_cfg_gop* cfg = v;
1273         void* cookie = NULL;
1274         AVP* avp;
1275         gint* ett;
1276         hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
1277
1278         hfri.p_id = &(cfg->hfid);
1279         hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
1280         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
1281         hfri.hfinfo.blurb = g_strdup_printf("%s id",cfg->name);
1282         hfri.hfinfo.type = FT_UINT32;
1283         hfri.hfinfo.display = BASE_DEC;
1284
1285         g_array_append_val(matecfg->hfrs,hfri);
1286
1287         hfri.p_id = &(cfg->hfid_start_time);
1288         hfri.hfinfo.name = g_strdup_printf("%s start time",cfg->name);
1289         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.StartTime",cfg->name);
1290         hfri.hfinfo.type = FT_FLOAT;
1291         hfri.hfinfo.display = BASE_DEC;
1292         hfri.hfinfo.blurb = g_strdup_printf("Seconds passed since the begining of caputre to the start of this %s",cfg->name);
1293
1294         g_array_append_val(matecfg->hfrs,hfri);
1295
1296         hfri.p_id = &(cfg->hfid_stop_time);
1297         hfri.hfinfo.name = g_strdup_printf("%s hold time",cfg->name);
1298         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Time",cfg->name);
1299         hfri.hfinfo.blurb = g_strdup_printf("Duration in seconds from start to stop of this %s",cfg->name);
1300
1301         g_array_append_val(matecfg->hfrs,hfri);
1302
1303         hfri.p_id = &(cfg->hfid_last_time);
1304         hfri.hfinfo.name = g_strdup_printf("%s duration",cfg->name);
1305         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Duration",cfg->name);
1306         hfri.hfinfo.blurb = g_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name);
1307
1308         g_array_append_val(matecfg->hfrs,hfri);
1309
1310         hfri.p_id = &(cfg->hfid_gop_num_pdus);
1311         hfri.hfinfo.name = g_strdup_printf("%s number of PDUs",cfg->name);
1312         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.NumOfPdus",cfg->name);
1313         hfri.hfinfo.blurb = g_strdup_printf("Number of PDUs assigned to this %s",cfg->name);
1314         hfri.hfinfo.type = FT_UINT32;
1315
1316         g_array_append_val(matecfg->hfrs,hfri);
1317
1318         hfri.p_id = &(cfg->hfid_gop_pdu);
1319         hfri.hfinfo.name = g_strdup_printf("A PDU of %s",cfg->name);
1320         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Pdu",cfg->name);
1321         hfri.hfinfo.blurb = g_strdup_printf("A PDU assigned to this %s",cfg->name);
1322
1323         if (cfg->show_pdu_tree == matecfg->frame_tree) {
1324                 hfri.hfinfo.type = FT_FRAMENUM;
1325                 g_array_append_val(matecfg->hfrs,hfri);
1326         } else  if (cfg->show_pdu_tree == matecfg->pdu_tree) {
1327                 hfri.hfinfo.type = FT_UINT32;
1328                 g_array_append_val(matecfg->hfrs,hfri);
1329         } else {
1330                 cfg->show_pdu_tree = matecfg->no_tree;
1331         }
1332
1333         while(( avp = get_next_avp(cfg->key,&cookie) )) {
1334                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1335                         new_attr_hfri(cfg,avp->n);
1336                 }
1337         }
1338
1339         if(cfg->start) {
1340                 cookie = NULL;
1341                 while(( avp = get_next_avp(cfg->start,&cookie) )) {
1342                         if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1343                                 new_attr_hfri(cfg,avp->n);
1344                         }
1345                 }
1346         }
1347         
1348         if (cfg->stop) {
1349                 cookie = NULL;
1350                 while(( avp = get_next_avp(cfg->stop,&cookie) )) {
1351                         if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1352                                 new_attr_hfri(cfg,avp->n);
1353                         }
1354                 }
1355         }
1356         
1357         cookie = NULL;
1358         while(( avp = get_next_avp(cfg->extra,&cookie) )) {
1359                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1360                         new_attr_hfri(cfg,avp->n);
1361                 }
1362         }
1363
1364         analyze_transform_hfrs(cfg);
1365
1366         ett = &cfg->ett;
1367         g_array_append_val(matecfg->ett,ett);
1368
1369         ett = &cfg->ett_attr;
1370         g_array_append_val(matecfg->ett,ett);
1371
1372         ett = &cfg->ett_times;
1373         g_array_append_val(matecfg->ett,ett);
1374
1375         ett = &cfg->ett_children;
1376         g_array_append_val(matecfg->ett,ett);
1377
1378 }
1379
1380
1381 static void analyze_gog_config(gpointer k _U_, gpointer v, gpointer p _U_) {
1382         mate_cfg_gop* cfg = v;
1383         void* avp_cookie;
1384         void* avpl_cookie;
1385         AVP* avp;
1386         AVPL* avpl;
1387         AVPL* key_avps;
1388         hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}};
1389         gint* ett;
1390
1391         hfri.p_id = &(cfg->hfid);
1392         hfri.hfinfo.name = g_strdup_printf("%s",cfg->name);
1393         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s",cfg->name);
1394         hfri.hfinfo.blurb = g_strdup_printf("%s Id",cfg->name);
1395         hfri.hfinfo.type = FT_UINT32;
1396         hfri.hfinfo.display = BASE_DEC;
1397
1398         g_array_append_val(matecfg->hfrs,hfri);
1399         
1400         hfri.p_id = &(cfg->hfid_gog_num_of_gops);
1401         hfri.hfinfo.name = "number of GOPs";
1402         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.NumOfGops",cfg->name);
1403         hfri.hfinfo.type = FT_UINT32;
1404         hfri.hfinfo.display = BASE_DEC;
1405         hfri.hfinfo.blurb = g_strdup_printf("Number of GOPs assigned to this %s",cfg->name);
1406         
1407         g_array_append_val(matecfg->hfrs,hfri);
1408         
1409         hfri.p_id = &(cfg->hfid_start_time);
1410         hfri.hfinfo.name = g_strdup_printf("%s start time",cfg->name);
1411         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.StartTime",cfg->name);
1412         hfri.hfinfo.type = FT_FLOAT;
1413         hfri.hfinfo.blurb = g_strdup_printf("Seconds passed since the begining of caputre to the start of this %s",cfg->name);
1414         
1415         g_array_append_val(matecfg->hfrs,hfri);
1416                 
1417         hfri.p_id = &(cfg->hfid_last_time);
1418         hfri.hfinfo.name = g_strdup_printf("%s duration",cfg->name);
1419         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Duration",cfg->name);
1420         hfri.hfinfo.blurb = g_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name);
1421         
1422         g_array_append_val(matecfg->hfrs,hfri);
1423         
1424         /* this might become mate.gogname.gopname */
1425         hfri.p_id = &(cfg->hfid_gog_gop);
1426         hfri.hfinfo.name = "a GOP";
1427         hfri.hfinfo.abbrev = g_strdup_printf("mate.%s.Gop",cfg->name);
1428         hfri.hfinfo.type = FT_STRING;
1429         hfri.hfinfo.display = BASE_DEC;
1430         hfri.hfinfo.blurb = g_strdup_printf("a GOPs assigned to this %s",cfg->name);
1431
1432         g_array_append_val(matecfg->hfrs,hfri);
1433
1434         key_avps = new_avpl("");
1435         
1436         avpl_cookie = NULL;
1437         while (( avpl = get_next_avpl(cfg->keys,&avpl_cookie) )) {
1438                 avp_cookie = NULL;
1439                 while (( avp = get_next_avp(avpl,&avp_cookie) )) {
1440                         if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1441                                 new_attr_hfri(cfg,avp->n);
1442                                 insert_avp(key_avps,avp);
1443                         }
1444                 }
1445         }
1446
1447         avp_cookie = NULL;
1448         while (( avp = get_next_avp(cfg->extra,&avp_cookie) )) {
1449                 if (! g_hash_table_lookup(cfg->my_hfids,avp->n))  {
1450                         new_attr_hfri(cfg,avp->n);
1451                 }
1452         }
1453         
1454         merge_avpl(cfg->extra,key_avps,TRUE);
1455         
1456         analyze_transform_hfrs(cfg);
1457
1458         ett = &cfg->ett;
1459         g_array_append_val(matecfg->ett,ett);
1460
1461         ett = &cfg->ett_attr;
1462         g_array_append_val(matecfg->ett,ett);
1463
1464         ett = &cfg->ett_children;
1465         g_array_append_val(matecfg->ett,ett);
1466
1467         ett = &cfg->ett_times;
1468         g_array_append_val(matecfg->ett,ett);
1469         
1470 }
1471
1472 static void analyze_config(void) {
1473         guint i;
1474
1475         for (i=0; i<matecfg->pducfglist->len; i++) {
1476                 analyze_pdu_config((mate_cfg_pdu*) g_ptr_array_index(matecfg->pducfglist,i));
1477         }
1478
1479         g_hash_table_foreach(matecfg->gopcfgs,analyze_gop_config,matecfg);
1480         g_hash_table_foreach(matecfg->gogcfgs,analyze_gog_config,matecfg);
1481
1482 }
1483
1484 static void new_action(guint8* name, config_action* action) {
1485         g_hash_table_insert(actions,name,action);
1486
1487 }
1488
1489 static void init_actions(void) {
1490         AVP* avp;
1491
1492         all_keywords = new_avpl("all_keywords");
1493
1494         insert_avp(all_keywords,new_avp(KEYWORD_ACTION,"",'='));
1495         insert_avp(all_keywords,new_avp(KEYWORD_SETTINGS,"",'='));
1496         insert_avp(all_keywords,new_avp(KEYWORD_INCLUDE,"",'='));
1497         insert_avp(all_keywords,new_avp(KEYWORD_TRANSFORM,"",'='));
1498         insert_avp(all_keywords,new_avp(KEYWORD_PDU,"",'='));
1499         insert_avp(all_keywords,new_avp(KEYWORD_PDUCRITERIA,"",'='));
1500         insert_avp(all_keywords,new_avp(KEYWORD_PDUEXTRA,"",'='));
1501         insert_avp(all_keywords,new_avp(KEYWORD_PDUTRANSFORM,"",'='));
1502         insert_avp(all_keywords,new_avp(KEYWORD_GOP,"",'='));
1503         insert_avp(all_keywords,new_avp(KEYWORD_GOPSTART,"",'='));
1504         insert_avp(all_keywords,new_avp(KEYWORD_GOPSTOP,"",'='));
1505         insert_avp(all_keywords,new_avp(KEYWORD_GOPEXTRA,"",'='));
1506         insert_avp(all_keywords,new_avp(KEYWORD_GOPTRANSFORM,"",'='));
1507         insert_avp(all_keywords,new_avp(KEYWORD_GOGDEF,"",'='));
1508         insert_avp(all_keywords,new_avp(KEYWORD_GOGKEY,"",'='));
1509         insert_avp(all_keywords,new_avp(KEYWORD_GOGEXTRA,"",'='));
1510         insert_avp(all_keywords,new_avp(KEYWORD_GOGTRANSFORM,"",'='));
1511         insert_avp(all_keywords,new_avp(KEYWORD_NAME,"",'='));
1512         insert_avp(all_keywords,new_avp(KEYWORD_ON,"",'='));
1513         insert_avp(all_keywords,new_avp(KEYWORD_FOR,"",'='));
1514         insert_avp(all_keywords,new_avp(KEYWORD_FROM,"",'='));
1515         insert_avp(all_keywords,new_avp(KEYWORD_TO,"",'='));
1516         insert_avp(all_keywords,new_avp(KEYWORD_MATCH,"",'='));
1517         insert_avp(all_keywords,new_avp(KEYWORD_MODE,"",'='));
1518         insert_avp(all_keywords,new_avp(KEYWORD_FILENAME,"",'='));
1519         insert_avp(all_keywords,new_avp(KEYWORD_PROTO,"",'='));
1520         insert_avp(all_keywords,new_avp(KEYWORD_METHOD,"",'='));
1521         insert_avp(all_keywords,new_avp(KEYWORD_TRANSPORT,"",'='));
1522         insert_avp(all_keywords,new_avp(KEYWORD_METHOD,"",'='));
1523         insert_avp(all_keywords,new_avp(KEYWORD_STRICT,"",'='));
1524         insert_avp(all_keywords,new_avp(KEYWORD_LOOSE,"",'='));
1525         insert_avp(all_keywords,new_avp(KEYWORD_EVERY,"",'='));
1526         insert_avp(all_keywords,new_avp(KEYWORD_REPLACE,"",'='));
1527         insert_avp(all_keywords,new_avp(KEYWORD_INSERT,"",'='));
1528         insert_avp(all_keywords,new_avp(KEYWORD_MAP,"",'='));
1529         insert_avp(all_keywords,new_avp(KEYWORD_GOGEXPIRE,"",'='));
1530         insert_avp(all_keywords,new_avp(KEYWORD_DISCARDPDU,"",'='));
1531         insert_avp(all_keywords,new_avp(KEYWORD_LIBPATH,"",'='));
1532         insert_avp(all_keywords,new_avp(KEYWORD_SHOWPDUTREE,"",'='));
1533         insert_avp(all_keywords,new_avp(KEYWORD_SHOWGOPTIMES,"",'='));
1534         insert_avp(all_keywords,new_avp(KEYWORD_STOP,"",'='));
1535         insert_avp(all_keywords,new_avp(KEYWORD_DROPPDU,"",'='));
1536         insert_avp(all_keywords,new_avp(KEYWORD_DROPGOP,"",'='));
1537         insert_avp(all_keywords,new_avp(KEYWORD_LIB,"",'='));
1538
1539         insert_avp(all_keywords,new_avp(KEYWORD_DBG_GENERAL,"",'='));
1540         insert_avp(all_keywords,new_avp(KEYWORD_DBG_CFG,"",'='));
1541         insert_avp(all_keywords,new_avp(KEYWORD_DBG_PDU,"",'='));
1542         insert_avp(all_keywords,new_avp(KEYWORD_DBG_GOP,"",'='));
1543         insert_avp(all_keywords,new_avp(KEYWORD_DBG_GOG,"",'='));
1544
1545 #ifdef _AVP_DEBUGGING
1546         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPLIB,"",'='));
1547         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVP,"",'='));
1548         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVP_OP,"",'='));
1549         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPL,"",'='));
1550         insert_avp(all_keywords,new_avp(KEYWORD_DBG_AVPL_OP,"",'='));
1551 #endif
1552
1553         avp = new_avp(KEYWORD_ACCEPT,"",'=');
1554         matecfg->accept = avp->n;
1555         insert_avp(all_keywords,avp);
1556
1557         avp = new_avp(KEYWORD_REJECT,"",'=');
1558         matecfg->reject = avp->n;
1559         insert_avp(all_keywords,avp);
1560
1561         avp = new_avp(KEYWORD_NOTREE,"",'=');
1562         matecfg->no_tree = avp->n;
1563         insert_avp(all_keywords,avp);
1564
1565         avp = new_avp(KEYWORD_FRAMETREE,"",'=');
1566         matecfg->frame_tree = avp->n;
1567         insert_avp(all_keywords,avp);
1568
1569         avp = new_avp(KEYWORD_PDUTREE,"",'=');
1570         matecfg->pdu_tree = avp->n;
1571         insert_avp(all_keywords,avp);
1572         
1573         if (actions) {
1574                 g_hash_table_destroy(actions);
1575         }
1576
1577         actions = g_hash_table_new(g_str_hash,g_str_equal);
1578
1579         new_action(KEYWORD_SETTINGS,config_settings);
1580         new_action(KEYWORD_PDU,config_pdu);
1581         new_action(KEYWORD_PDUEXTRA,config_pduextra);
1582         new_action(KEYWORD_PDUCRITERIA,config_pducriteria);
1583         new_action(KEYWORD_GOP,config_gop);
1584         new_action(KEYWORD_GOGDEF,config_gog);
1585         new_action(KEYWORD_GOGKEY,config_gogkey);
1586         new_action(KEYWORD_GOPSTART,config_start);
1587         new_action(KEYWORD_GOPSTOP,config_stop);
1588         new_action(KEYWORD_GOPEXTRA,config_gopextra);
1589         new_action(KEYWORD_GOGEXTRA,config_gogextra);
1590         new_action(KEYWORD_INCLUDE,config_include);
1591         new_action(KEYWORD_TRANSFORM,config_transform);
1592         new_action(KEYWORD_PDUTRANSFORM,config_pdu_transform);
1593         new_action(KEYWORD_GOPTRANSFORM,config_gop_transform);
1594         new_action(KEYWORD_GOGTRANSFORM,config_gog_transform);
1595
1596 }
1597
1598 extern mate_config* mate_cfg() {
1599         return matecfg;
1600 }
1601
1602 extern mate_config* mate_make_config(guint8* filename, int mate_hfid) {
1603         gint* ett;
1604
1605         avp_init();
1606
1607         matecfg = g_malloc(sizeof(mate_config));
1608
1609         matecfg->gog_expiration = DEFAULT_GOG_EXPIRATION;
1610         matecfg->discard_pdu_attributes = FALSE;
1611         matecfg->drop_pdu = FALSE;
1612         matecfg->drop_gop = FALSE;
1613         matecfg->show_times = TRUE;
1614         matecfg->last_to_be_created = FALSE;
1615         matecfg->match_mode = AVPL_STRICT;
1616         matecfg->replace_mode = AVPL_INSERT;
1617         matecfg->mate_lib_path = g_strdup_printf("%s%c%s%c",get_datafile_dir(),DIR_SEP,DEFAULT_MATE_LIB_PATH,DIR_SEP);
1618         matecfg->mate_config_file = g_strdup(filename);
1619         matecfg->mate_attrs_filter = g_string_new("");
1620         matecfg->mate_protos_filter = g_string_new("");
1621         matecfg->dbg_facility = NULL;
1622         matecfg->dbg_lvl = 0;
1623         matecfg->dbg_cfg_lvl = 0;
1624         matecfg->dbg_pdu_lvl = 0;
1625         matecfg->dbg_gop_lvl = 0;
1626         matecfg->dbg_gog_lvl = 0;
1627         matecfg->pducfglist = g_ptr_array_new();
1628         matecfg->pducfgs = g_hash_table_new(g_str_hash,g_str_equal);
1629         matecfg->gopcfgs = g_hash_table_new(g_str_hash,g_str_equal);
1630         matecfg->gogcfgs = g_hash_table_new(g_str_hash,g_str_equal);
1631         matecfg->transfs = g_hash_table_new(g_str_hash,g_str_equal);
1632         matecfg->gops_by_pduname = g_hash_table_new(g_str_hash,g_str_equal);
1633         matecfg->gogs_by_gopname = g_hash_table_new(g_str_hash,g_str_equal);
1634
1635         matecfg->hfrs = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
1636         matecfg->ett = g_array_new(FALSE,TRUE,sizeof(gint*));
1637         matecfg->ett_root = -1;
1638         matecfg->hfid_mate = mate_hfid;
1639         
1640         ett = &matecfg->ett_root;
1641         g_array_append_val(matecfg->ett,ett);
1642
1643         dbg = &matecfg->dbg_lvl;
1644
1645         init_actions();
1646
1647         matecfg->show_pdu_tree = matecfg->frame_tree;
1648
1649         config_error = g_string_new("");
1650         
1651         if ( mate_load_config(filename) ) {
1652                 analyze_config();
1653                 dbg_print (dbg_cfg,3,dbg_facility,"mate_make_config: OK");
1654                 if (dbg_cfg_lvl > 0) print_config();
1655         } else {
1656                 report_failure("%s",config_error->str);
1657                 g_string_free(config_error,TRUE);
1658                 if (matecfg) destroy_mate_config(matecfg,FALSE);
1659                 matecfg = NULL;
1660                 return NULL;
1661         }
1662
1663         if (matecfg->mate_attrs_filter->len > 1) {
1664                 g_string_erase(matecfg->mate_attrs_filter,0,2);
1665                 g_string_erase(matecfg->mate_protos_filter,0,2);
1666         } else {
1667                 destroy_mate_config(matecfg,FALSE);
1668                 matecfg = NULL;
1669                 return NULL;
1670         }
1671
1672         matecfg->tap_filter = g_strdup_printf("(%s) && (%s)",matecfg->mate_protos_filter->str,matecfg->mate_attrs_filter->str);
1673
1674         return matecfg;
1675 }
1676