2 * MATE -- Meta Analysis Tracing Engine
4 * Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 typedef struct _mate_range mate_range
;
37 typedef struct _tmp_pdu_data
{
44 typedef struct _gogkey
{
50 static mate_runtime_data
* rd
= NULL
;
51 static mate_config
* mc
= NULL
;
55 static int* dbg
= &zero
;
56 static int* dbg_pdu
= &zero
;
57 static int* dbg_gop
= &zero
;
58 static int* dbg_gog
= &zero
;
59 static FILE* dbg_facility
= NULL
;
61 static gboolean
destroy_mate_pdus(gpointer k _U_
, gpointer v
, gpointer p _U_
) {
62 mate_pdu
* pdu
= (mate_pdu
*) v
;
63 if (pdu
->avpl
) delete_avpl(pdu
->avpl
,TRUE
);
64 g_slice_free(mate_max_size
, (mate_max_size
*)pdu
);
68 static gboolean
destroy_mate_gops(gpointer k _U_
, gpointer v
, gpointer p _U_
) {
69 mate_gop
* gop
= (mate_gop
*) v
;
71 if (gop
->avpl
) delete_avpl(gop
->avpl
,TRUE
);
74 if (g_hash_table_lookup(gop
->cfg
->gop_index
,gop
->gop_key
) == gop
) {
75 g_hash_table_remove(gop
->cfg
->gop_index
,gop
->gop_key
);
81 g_slice_free(mate_max_size
,(mate_max_size
*)gop
);
87 static void gog_remove_keys (mate_gog
* gog
);
89 static gboolean
destroy_mate_gogs(gpointer k _U_
, gpointer v
, gpointer p _U_
) {
90 mate_gog
* gog
= (mate_gog
*) v
;
92 if (gog
->avpl
) delete_avpl(gog
->avpl
,TRUE
);
96 g_ptr_array_free(gog
->gog_keys
,FALSE
);
99 g_slice_free(mate_max_size
,(mate_max_size
*)gog
);
104 static gboolean
return_true(gpointer k _U_
, gpointer v _U_
, gpointer p _U_
) {
108 static void destroy_pdus_in_cfg(gpointer k _U_
, gpointer v
, gpointer p _U_
) {
109 mate_cfg_pdu
* c
= (mate_cfg_pdu
*)v
;
110 g_hash_table_foreach_remove(c
->items
,destroy_mate_pdus
,NULL
);
115 static void destroy_gops_in_cfg(gpointer k _U_
, gpointer v
, gpointer p _U_
) {
116 mate_cfg_gop
* c
= (mate_cfg_gop
*)v
;
118 g_hash_table_foreach_remove(c
->gop_index
,return_true
,NULL
);
119 g_hash_table_destroy(c
->gop_index
);
120 c
->gop_index
= g_hash_table_new(g_str_hash
,g_str_equal
);
122 g_hash_table_foreach_remove(c
->gog_index
,return_true
,NULL
);
123 g_hash_table_destroy(c
->gog_index
);
124 c
->gog_index
= g_hash_table_new(g_str_hash
,g_str_equal
);
126 g_hash_table_foreach_remove(c
->items
,destroy_mate_gops
,NULL
);
130 static void destroy_gogs_in_cfg(gpointer k _U_
, gpointer v
, gpointer p _U_
) {
131 mate_cfg_gog
* c
= (mate_cfg_gog
*)v
;
132 g_hash_table_foreach_remove(c
->items
,destroy_mate_gogs
,NULL
);
136 extern void initialize_mate_runtime(void) {
138 dbg_print (dbg
,5,dbg_facility
,"initialize_mate: entering");
140 if (( mc
= mate_cfg() )) {
142 rd
= (mate_runtime_data
*)g_malloc(sizeof(mate_runtime_data
));
144 g_hash_table_foreach(mc
->pducfgs
,destroy_pdus_in_cfg
,NULL
);
145 g_hash_table_foreach(mc
->gopcfgs
,destroy_gops_in_cfg
,NULL
);
146 g_hash_table_foreach(mc
->gogcfgs
,destroy_gogs_in_cfg
,NULL
);
148 g_hash_table_destroy(rd
->frames
);
151 rd
->current_items
= 0;
153 rd
->highest_analyzed_frame
= 0;
154 rd
->frames
= g_hash_table_new(g_direct_hash
,g_direct_equal
);
157 /*mc->dbg_gop_lvl = 5;
160 dbg_pdu
= &(mc
->dbg_pdu_lvl
);
161 dbg_gop
= &(mc
->dbg_gop_lvl
);
162 dbg_gog
= &(mc
->dbg_gog_lvl
);
163 dbg
= &(mc
->dbg_lvl
);
164 dbg_facility
= mc
->dbg_facility
;
166 dbg_print(dbg
, 1, dbg_facility
, "starting mate");
174 static mate_gop
* new_gop(mate_cfg_gop
* cfg
, mate_pdu
* pdu
, gchar
* key
) {
175 mate_gop
* gop
= (mate_gop
*)g_slice_new(mate_max_size
);
177 gop
->id
= ++(cfg
->last_id
);
180 dbg_print(dbg_gop
, 1, dbg_facility
, "new_gop: %s: ``%s:%d''", key
, gop
->cfg
->name
, gop
->id
);
183 gop
->avpl
= new_avpl(cfg
->name
);
189 gop
->expiration
= cfg
->expiration
> 0.0 ? cfg
->expiration
+ rd
->now
: (float) -1.0 ;
190 gop
->idle_expiration
= cfg
->idle_timeout
> 0.0 ? cfg
->idle_timeout
+ rd
->now
: (float) -1.0 ;
191 gop
->time_to_die
= cfg
->lifetime
> 0.0 ? cfg
->lifetime
+ rd
->now
: (float) -1.0 ;
192 gop
->time_to_timeout
= 0.0f
;
194 gop
->last_time
= gop
->start_time
= rd
->now
;
195 gop
->release_time
= 0.0f
;
197 gop
->num_of_pdus
= 0;
198 gop
->num_of_after_release_pdus
= 0;
203 gop
->released
= FALSE
;
207 pdu
->is_start
= TRUE
;
208 pdu
->time_in_gop
= 0.0f
;
210 g_hash_table_insert(cfg
->gop_index
,gop
->gop_key
,gop
);
214 static void adopt_gop(mate_gog
* gog
, mate_gop
* gop
) {
215 dbg_print (dbg_gog
,5,dbg_facility
,"adopt_gop: gog=%X gop=%X",gog
,gop
);
220 if (gop
->cfg
->start
) {
221 gog
->num_of_counting_gops
++;
227 gog
->last_gop
->next
= gop
;
238 static mate_gog
* new_gog(mate_cfg_gog
* cfg
, mate_gop
* gop
) {
239 mate_gog
* gog
= (mate_gog
*)g_slice_new(mate_max_size
);
240 gog
->id
= ++(cfg
->last_id
);
243 dbg_print (dbg_gog
,1,dbg_facility
,"new_gog: %s:%u for %s:%u",gog
->cfg
->name
,gog
->id
,gop
->cfg
->name
,gop
->id
);
245 gog
->avpl
= new_avpl(cfg
->name
);
248 gog
->expiration
= 0.0f
;
249 gog
->idle_expiration
= 0.0f
;
251 gog
->start_time
= rd
->now
;
252 gog
->release_time
= 0.0f
;
253 gog
->last_time
= 0.0f
;
256 gog
->last_gop
= NULL
;
258 gog
->num_of_gops
= 0;
259 gog
->num_of_counting_gops
= 0;
260 gog
->num_of_released_gops
= 0;
262 gog
->gog_keys
= g_ptr_array_new();
269 static void apply_transforms(GPtrArray
* transforms
, AVPL
* avpl
) {
270 AVPL_Transf
* transform
= NULL
;
273 for (i
= 0; i
< transforms
->len
; i
++) {
274 transform
= (AVPL_Transf
*)g_ptr_array_index(transforms
,i
);
275 avpl_transform(avpl
, transform
);
280 /* applies the extras for which type to what avpl */
281 static void apply_extras(AVPL
* from
, AVPL
* to
, AVPL
* extras
) {
282 AVPL
* our_extras
= new_avpl_loose_match("",from
, extras
, FALSE
) ;
285 merge_avpl(to
,our_extras
,TRUE
);
286 delete_avpl(our_extras
,FALSE
);
290 static void gog_remove_keys (mate_gog
* gog
) {
293 while (gog
->gog_keys
->len
) {
294 gog_key
= (gogkey
*)g_ptr_array_remove_index_fast(gog
->gog_keys
,0);
296 if (g_hash_table_lookup(gog_key
->cfg
->gog_index
,gog_key
->key
) == gog
) {
297 g_hash_table_remove(gog_key
->cfg
->gog_index
,gog_key
->key
);
300 g_free(gog_key
->key
);
306 static void reanalyze_gop(mate_gop
* gop
) {
307 LoAL
* gog_keys
= NULL
;
308 AVPL
* curr_gogkey
= NULL
;
309 mate_cfg_gop
* gop_cfg
= NULL
;
311 AVPL
* gogkey_match
= NULL
;
312 mate_gog
* gog
= gop
->gog
;
317 gog
->last_time
= rd
->now
;
319 dbg_print (dbg_gog
,1,dbg_facility
,"reanalyze_gop: %s:%d",gop
->cfg
->name
,gop
->id
);
321 apply_extras(gop
->avpl
,gog
->avpl
,gog
->cfg
->extra
);
323 /* XXX: Instead of using the length of the avpl to check if an avpl has changed,
324 which is not accurate at all, we should have apply_extras,
325 apply_transformations and other functions that can modify the avpl
326 to flag the avpl if it has changed, then we'll check for the flag
327 and clear it after analysis */
329 if (gog
->last_n
!= gog
->avpl
->len
) {
331 dbg_print (dbg_gog
,2,dbg_facility
,"reanalyze_gop: gog has new attributes let's look for new keys");
333 gog_keys
= gog
->cfg
->keys
;
335 while (( curr_gogkey
= get_next_avpl(gog_keys
,&cookie
) )) {
336 gop_cfg
= (mate_cfg_gop
*)g_hash_table_lookup(mc
->gopcfgs
,curr_gogkey
->name
);
338 if (( gogkey_match
= new_avpl_exact_match(gop_cfg
->name
,gog
->avpl
,curr_gogkey
,FALSE
) )) {
340 gog_key
= (gogkey
*)g_malloc(sizeof(gogkey
));
342 gog_key
->key
= avpl_to_str(gogkey_match
);
343 delete_avpl(gogkey_match
,FALSE
);
345 gog_key
->cfg
= gop_cfg
;
347 if (g_hash_table_lookup(gop_cfg
->gog_index
,gog_key
->key
)) {
348 g_free(gog_key
->key
);
354 /* XXX: since these gogs actually share key info
355 we should try to merge (non released) gogs
356 that happen to have equal keys */
358 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: new key for gog=%s:%d : %s",gog
->cfg
->name
,gog
->id
,gog_key
->key
);
359 g_ptr_array_add(gog
->gog_keys
,gog_key
);
360 g_hash_table_insert(gog_key
->cfg
->gog_index
,gog_key
->key
,gog
);
366 gog
->last_n
= gog
->avpl
->len
;
369 if (gog
->num_of_released_gops
== gog
->num_of_counting_gops
) {
370 gog
->released
= TRUE
;
371 gog
->expiration
= gog
->cfg
->expiration
+ rd
->now
;
373 gog
->released
= FALSE
;
377 static void analyze_gop(mate_gop
* gop
) {
378 mate_cfg_gog
* cfg
= NULL
;
379 LoAL
* gog_keys
= NULL
;
380 AVPL
* curr_gogkey
= NULL
;
382 AVPL
* gogkey_match
= NULL
;
383 mate_gog
* gog
= NULL
;
387 /* no gog, let's either find one or create it if due */
388 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: no gog");
390 gog_keys
= (LoAL
*)g_hash_table_lookup(mc
->gogs_by_gopname
,gop
->cfg
->name
);
393 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: no gog_keys for this gop");
397 /* We have gog_keys! look for matching gogkeys */
399 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: got gog_keys: %s",gog_keys
->name
) ;
401 while (( curr_gogkey
= get_next_avpl(gog_keys
,&cookie
) )) {
402 if (( gogkey_match
= new_avpl_exact_match(gop
->cfg
->name
,gop
->avpl
,curr_gogkey
,TRUE
) )) {
404 key
= avpl_to_str(gogkey_match
);
406 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: got gogkey_match: %s",key
);
408 if (( gog
= (mate_gog
*)g_hash_table_lookup(gop
->cfg
->gog_index
,key
) )) {
409 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: got already a matching gog");
411 if (gog
->num_of_counting_gops
== gog
->num_of_released_gops
&& gog
->expiration
< rd
->now
) {
412 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: this is a new gog, not the old one, let's create it");
414 gog_remove_keys(gog
);
416 new_gog(gog
->cfg
,gop
);
420 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: this is our gog");
422 if (! gop
->gog
) adopt_gop(gog
,gop
);
427 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: no such gog in hash, let's create a new %s",curr_gogkey
->name
);
429 cfg
= (mate_cfg_gog
*)g_hash_table_lookup(mc
->gogcfgs
,curr_gogkey
->name
);
432 gog
= new_gog(cfg
,gop
);
433 gog
->num_of_gops
= 1;
435 if (gop
->cfg
->start
) {
436 gog
->num_of_counting_gops
= 1;
440 dbg_print (dbg_gog
,0,dbg_facility
,"analyze_gop: no such gog_cfg: %s",curr_gogkey
->name
);
446 /** Can't get here because of "breaks" above */
447 g_assert_not_reached();
450 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: no gogkey_match: %s",key
);
456 if (gogkey_match
) delete_avpl(gogkey_match
,TRUE
);
464 static void analyze_pdu(mate_pdu
* pdu
) {
466 return a g_boolean to tell we've destroyed the pdu when the pdu is unnassigned
467 destroy the unassigned pdu
469 mate_cfg_gop
* cfg
= NULL
;
470 mate_gop
* gop
= NULL
;
472 gchar
* orig_gop_key
= NULL
;
473 AVPL
* candidate_start
= NULL
;
474 AVPL
* candidate_stop
= NULL
;
475 AVPL
* is_start
= NULL
;
476 AVPL
* is_stop
= NULL
;
477 AVPL
* gopkey_match
= NULL
;
478 LoAL
* gog_keys
= NULL
;
479 AVPL
* curr_gogkey
= NULL
;
481 AVPL
* gogkey_match
= NULL
;
482 gchar
* gogkey_str
= NULL
;
484 dbg_print (dbg_gop
,1,dbg_facility
,"analyze_pdu: %s",pdu
->cfg
->name
);
486 if (! (cfg
= (mate_cfg_gop
*)g_hash_table_lookup(mc
->gops_by_pduname
,pdu
->cfg
->name
)) )
489 if ((gopkey_match
= new_avpl_exact_match("gop_key_match",pdu
->avpl
,cfg
->key
, TRUE
))) {
490 gop_key
= avpl_to_str(gopkey_match
);
492 g_hash_table_lookup_extended(cfg
->gop_index
,(gconstpointer
)gop_key
,(gpointer
*)&orig_gop_key
,(gpointer
*)&gop
);
497 /* is the gop dead ? */
498 if ( ! gop
->released
&&
499 ( ( gop
->cfg
->lifetime
> 0.0 && gop
->time_to_die
>= rd
->now
) ||
500 ( gop
->cfg
->idle_timeout
> 0.0 && gop
->time_to_timeout
>= rd
->now
) ) ) {
501 dbg_print (dbg_gop
,4,dbg_facility
,"analyze_pdu: expiring released gop");
502 gop
->released
= TRUE
;
504 if (gop
->gog
&& gop
->cfg
->start
) gop
->gog
->num_of_released_gops
++;
507 /* TODO: is the gop expired? */
509 gop_key
= orig_gop_key
;
511 dbg_print (dbg_gop
,2,dbg_facility
,"analyze_pdu: got gop: %s",gop_key
);
513 if (( candidate_start
= cfg
->start
)) {
515 dbg_print (dbg_gop
,2,dbg_facility
,"analyze_pdu: got candidate start");
517 if (( is_start
= new_avpl_exact_match("",pdu
->avpl
, candidate_start
, FALSE
) )) {
518 delete_avpl(is_start
,FALSE
);
519 if ( gop
->released
) {
520 dbg_print (dbg_gop
,3,dbg_facility
,"analyze_pdu: start on released gop, let's create a new gop");
522 g_hash_table_remove(cfg
->gop_index
,gop_key
);
524 gop
= new_gop(cfg
,pdu
,gop_key
);
525 g_hash_table_insert(cfg
->gop_index
,gop_key
,gop
);
527 dbg_print (dbg_gop
,1,dbg_facility
,"analyze_pdu: duplicate start on gop");
534 if (gop
->last_pdu
) gop
->last_pdu
->next
= pdu
;
537 pdu
->time_in_gop
= rd
->now
- gop
->start_time
;
539 if (gop
->released
) pdu
->after_release
= TRUE
;
543 dbg_print (dbg_gop
,1,dbg_facility
,"analyze_pdu: no gop already");
545 if ( ! cfg
->start
) {
546 /* there is no GopStart, we'll check for matching GogKeys
547 if we have one we'll create the Gop */
549 apply_extras(pdu
->avpl
,gopkey_match
,cfg
->extra
);
551 gog_keys
= (LoAL
*)g_hash_table_lookup(mc
->gogs_by_gopname
,cfg
->name
);
555 while (( curr_gogkey
= get_next_avpl(gog_keys
,&cookie
) )) {
556 if (( gogkey_match
= new_avpl_exact_match(cfg
->name
,gopkey_match
,curr_gogkey
,FALSE
) )) {
557 gogkey_str
= avpl_to_str(gogkey_match
);
559 if (g_hash_table_lookup(cfg
->gog_index
,gogkey_str
)) {
560 gop
= new_gop(cfg
,pdu
,gop_key
);
561 g_hash_table_insert(cfg
->gop_index
,gop_key
,gop
);
562 delete_avpl(gogkey_match
,FALSE
);
566 delete_avpl(gogkey_match
,FALSE
);
574 delete_avpl(gopkey_match
,TRUE
);
580 delete_avpl(gopkey_match
,TRUE
);
585 candidate_start
= cfg
->start
;
587 if (( is_start
= new_avpl_exact_match("",pdu
->avpl
, candidate_start
, FALSE
) )) {
588 delete_avpl(is_start
,FALSE
);
589 gop
= new_gop(cfg
,pdu
,gop_key
);
599 if (gop
->last_pdu
) gop
->last_pdu
->next
= pdu
;
603 pdu
->time_in_gop
= rd
->now
- gop
->start_time
;
606 gop
->time_to_timeout
= cfg
->idle_timeout
> 0.0 ? cfg
->idle_timeout
+ rd
->now
: (float) -1.0 ;
608 dbg_print (dbg_gop
,4,dbg_facility
,"analyze_pdu: merge with key");
610 merge_avpl(gop
->avpl
,gopkey_match
,TRUE
);
611 delete_avpl(gopkey_match
,TRUE
);
613 dbg_print (dbg_gop
,4,dbg_facility
,"analyze_pdu: apply extras");
615 apply_extras(pdu
->avpl
,gop
->avpl
,gop
->cfg
->extra
);
617 gop
->last_time
= pdu
->rel_time
;
619 if ( ! gop
->released
) {
620 candidate_stop
= cfg
->stop
;
622 if (candidate_stop
) {
623 is_stop
= new_avpl_exact_match("",pdu
->avpl
, candidate_stop
,FALSE
);
625 is_stop
= new_avpl("");
629 dbg_print (dbg_gop
,1,dbg_facility
,"analyze_pdu: is a `stop");
630 delete_avpl(is_stop
,FALSE
);
632 if (! gop
->released
) {
633 gop
->released
= TRUE
;
634 gop
->release_time
= pdu
->rel_time
;
635 if (gop
->gog
&& gop
->cfg
->start
) gop
->gog
->num_of_released_gops
++;
643 if (gop
->last_n
!= gop
->avpl
->len
) apply_transforms(gop
->cfg
->transforms
,gop
->avpl
);
645 gop
->last_n
= gop
->avpl
->len
;
654 dbg_print (dbg_gop
,4,dbg_facility
,"analyze_pdu: no match for this pdu");
660 static void get_pdu_fields(gpointer k
, gpointer v
, gpointer p
) {
661 int hfid
= *((int*) k
);
662 gchar
* name
= (gchar
*) v
;
663 tmp_pdu_data
* data
= (tmp_pdu_data
*) p
;
667 mate_range
* curr_range
;
674 fis
= proto_get_finfo_ptr_array(data
->tree
, hfid
);
677 for (i
= 0; i
< fis
->len
; i
++) {
678 fi
= (field_info
*) g_ptr_array_index(fis
,i
);
682 end
= fi
->start
+ fi
->length
;
684 dbg_print(dbg_pdu
,5,dbg_facility
,"get_pdu_fields: found field %i-%i",start
,end
);
686 for (j
= 0; j
< data
->ranges
->len
; j
++) {
688 curr_range
= (mate_range
*) g_ptr_array_index(data
->ranges
,j
);
690 if (curr_range
->end
>= end
&& curr_range
->start
<= start
) {
691 avp
= new_avp_from_finfo(name
, fi
);
695 dbg_print(dbg_pdu
,0,dbg_facility
,"get_pdu_fields: got %s",s
);
699 if (! insert_avp(data
->pdu
->avpl
,avp
) ) {
709 static mate_pdu
* new_pdu(mate_cfg_pdu
* cfg
, guint32 framenum
, field_info
* proto
, proto_tree
* tree
) {
710 mate_pdu
* pdu
= (mate_pdu
*)g_slice_new(mate_max_size
);
714 mate_range
* proto_range
;
718 field_info
* range_fi
;
724 dbg_print (dbg_pdu
,1,dbg_facility
,"new_pdu: type=%s framenum=%i",cfg
->name
,framenum
);
726 pdu
->id
= ++(cfg
->last_id
);
729 pdu
->avpl
= new_avpl(cfg
->name
);
731 pdu
->frame
= framenum
;
732 pdu
->next_in_frame
= NULL
;
733 pdu
->rel_time
= rd
->now
;
737 pdu
->time_in_gop
= -1.0f
;
740 pdu
->is_start
= FALSE
;
741 pdu
->is_stop
= FALSE
;
742 pdu
->after_release
= FALSE
;
744 data
.ranges
= g_ptr_array_new();
748 /* first we create the proto range */
749 proto_range
= (mate_range
*)g_malloc(sizeof(mate_range
));
750 proto_range
->start
= proto
->start
;
751 proto_range
->end
= proto
->start
+ proto
->length
;
752 g_ptr_array_add(data
.ranges
,proto_range
);
754 dbg_print(dbg_pdu
,3,dbg_facility
,"new_pdu: proto range %u-%u",proto_range
->start
,proto_range
->end
);
756 last_start
= proto_range
->start
;
758 /* we move forward in the tranport */
759 for (i
= cfg
->transport_ranges
->len
; i
--; ) {
760 hfid
= *((int*)g_ptr_array_index(cfg
->transport_ranges
,i
));
761 ptrs
= proto_get_finfo_ptr_array(tree
, hfid
);
766 for (j
=0; j
< ptrs
->len
; j
++) {
767 cfi
= (field_info
*) g_ptr_array_index(ptrs
,j
);
768 if (cfi
->start
< last_start
&& min_dist
>= (last_start
- cfi
->start
) ) {
770 min_dist
= last_start
- cfi
->start
;
775 range
= (mate_range
*)g_malloc(sizeof(*range
));
776 range
->start
= range_fi
->start
;
777 range
->end
= range_fi
->start
+ range_fi
->length
;
778 g_ptr_array_add(data
.ranges
,range
);
780 last_start
= range_fi
->start
;
782 dbg_print(dbg_pdu
,3,dbg_facility
,"new_pdu: transport(%i) range %i-%i",hfid
,range
->start
,range
->end
);
784 /* we missed a range */
785 dbg_print(dbg_pdu
,6,dbg_facility
,"new_pdu: transport(%i) missed",hfid
);
791 if (cfg
->payload_ranges
) {
793 first_end
= proto_range
->end
;
795 for (i
= 0 ; i
< cfg
->payload_ranges
->len
; i
++) {
796 hfid
= *((int*)g_ptr_array_index(cfg
->payload_ranges
,i
));
797 ptrs
= proto_get_finfo_ptr_array(tree
, hfid
);
802 for (j
=0; j
< ptrs
->len
; j
++) {
803 cfi
= (field_info
*) g_ptr_array_index(ptrs
,j
);
804 curr_end
= cfi
->start
+ cfi
->length
;
805 if (curr_end
> first_end
&& min_dist
>= (curr_end
- first_end
) ) {
807 min_dist
= curr_end
- first_end
;
812 range
= (mate_range
*)g_malloc(sizeof(*range
));
813 range
->start
= range_fi
->start
;
814 range
->end
= range_fi
->start
+ range_fi
->length
;
815 g_ptr_array_add(data
.ranges
,range
);
817 dbg_print(dbg_pdu
,3,dbg_facility
,"new_pdu: payload(%i) range %i-%i",hfid
,range
->start
,range
->end
);
819 /* we missed a range */
820 dbg_print(dbg_pdu
,5,dbg_facility
,"new_pdu: payload(%i) missed",hfid
);
827 g_hash_table_foreach(cfg
->hfids_attr
,get_pdu_fields
,&data
);
829 apply_transforms(pdu
->cfg
->transforms
,pdu
->avpl
);
831 g_ptr_array_free(data
.ranges
,TRUE
);
837 extern void mate_analyze_frame(packet_info
*pinfo
, proto_tree
* tree
) {
842 AVPL
* criterium_match
;
844 mate_pdu
* pdu
= NULL
;
845 mate_pdu
* last
= NULL
;
847 rd
->now
= (float) nstime_to_sec(&pinfo
->rel_ts
);
849 if ( proto_tracking_interesting_fields(tree
)
850 && rd
->highest_analyzed_frame
< pinfo
->fd
->num
) {
851 for ( i
= 0; i
< mc
->pducfglist
->len
; i
++ ) {
853 cfg
= (mate_cfg_pdu
*)g_ptr_array_index(mc
->pducfglist
,i
);
855 dbg_print (dbg_pdu
,4,dbg_facility
,"mate_analyze_frame: trying to extract: %s",cfg
->name
);
856 protos
= proto_get_finfo_ptr_array(tree
, cfg
->hfid_proto
);
861 for (j
= 0; j
< protos
->len
; j
++) {
863 dbg_print (dbg_pdu
,3,dbg_facility
,"mate_analyze_frame: found matching proto, extracting: %s",cfg
->name
);
865 proto
= (field_info
*) g_ptr_array_index(protos
,j
);
866 pdu
= new_pdu(cfg
, pinfo
->fd
->num
, proto
, tree
);
868 if (cfg
->criterium
) {
869 criterium_match
= new_avpl_from_match(cfg
->criterium_match_mode
,"",pdu
->avpl
,cfg
->criterium
,FALSE
);
871 if (criterium_match
) {
872 delete_avpl(criterium_match
,FALSE
);
875 if ( (criterium_match
&& cfg
->criterium_accept_mode
== REJECT_MODE
)
876 || ( ! criterium_match
&& cfg
->criterium_accept_mode
== ACCEPT_MODE
)) {
878 delete_avpl(pdu
->avpl
,TRUE
);
879 g_slice_free(mate_max_size
,(mate_max_size
*)pdu
);
888 if ( ! pdu
->gop
&& cfg
->drop_unassigned
) {
889 delete_avpl(pdu
->avpl
,TRUE
);
890 g_slice_free(mate_max_size
,(mate_max_size
*)pdu
);
895 if ( cfg
->discard
) {
896 delete_avpl(pdu
->avpl
,TRUE
);
901 g_hash_table_insert(rd
->frames
,GINT_TO_POINTER(pinfo
->fd
->num
),pdu
);
904 last
->next_in_frame
= pdu
;
910 if ( pdu
&& cfg
->last_extracted
) break;
914 rd
->highest_analyzed_frame
= pinfo
->fd
->num
;
918 extern mate_pdu
* mate_get_pdus(guint32 framenum
) {
921 return (mate_pdu
*) g_hash_table_lookup(rd
->frames
,GUINT_TO_POINTER(framenum
));